Program to find maximum possible population of all the cities in python

Consider a country represented as a tree with N nodes and N-1 edges. Each node represents a town, and each edge represents a bidirectional road. We need to upgrade some towns into cities following these constraints: no two cities should be adjacent, and every town must be adjacent to at least one city. Our goal is to find the maximum possible population of all upgraded cities.

Problem Understanding

Given source and dest arrays representing road connections, and a population array for each town, we need to select nodes (upgrade to cities) such that ?

  • No two selected nodes are adjacent
  • Every unselected node has at least one selected neighbor
  • Total population of selected nodes is maximized

For example, with source = [2, 2, 1, 1], dest = [1, 3, 4, 0], population = [6, 8, 4, 3, 5], we can upgrade cities 0, 2, and 4 to get population 6 + 4 + 5 = 15.

Algorithm Explanation

This is a classic bipartite graph coloring problem. Since the graph is a tree, we can use DFS to try both possibilities for the root node and take the maximum ?

  1. Build adjacency list from source and dest arrays
  2. Use DFS with two states: choose current node or don't choose it
  3. For each node, if we choose it, add its population and don't choose neighbors
  4. If we don't choose it, we must choose all neighbors
  5. Return maximum of both possibilities

Implementation

from collections import defaultdict

class Solution:
    def solve(self, source, dest, population):
        # Build adjacency list
        adj = defaultdict(list)
        for a, b in zip(source, dest):
            adj[a].append(b)
            adj[b].append(a)
        
        seen = set()
        
        def dfs(x, choose):
            if x in seen:
                return 0
            seen.add(x)
            
            ans = 0
            if choose:
                ans += population[x]
            
            for neighbor in adj[x]:
                ans += dfs(neighbor, not choose)
            
            return ans
        
        # Try choosing root node vs not choosing it
        x = dfs(0, True)
        return max(x, sum(population) - x)

# Test the solution
ob = Solution()
source = [2, 2, 1, 1]
dest = [1, 3, 4, 0]
population = [6, 8, 4, 3, 5]
print(ob.solve(source, dest, population))

The output of the above code is ?

15

How It Works

The DFS function explores the tree with a boolean choose parameter. When choose is True, we include the current node's population and recursively process neighbors with choose=False. When choose is False, we skip the current node and process neighbors with choose=True.

Since we start with an arbitrary root (node 0), we try both possibilities: choosing the root or not choosing it. The answer is the maximum of these two scenarios.

Conclusion

This solution uses DFS with bipartite coloring to solve the maximum weighted independent set problem on a tree. The time complexity is O(N) and space complexity is O(N) for the adjacency list and recursion stack.

Updated on: 2026-03-25T13:10:14+05:30

753 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements