Maximum Total Importance of Roads
MedPrompt
You are given an integer n denoting the number of cities in a country. The cities are numbered from 0 to n - 1.
You are also given a 2D integer array roads where roads[i] = [ai, bi] denotes that there exists a bidirectional road connecting cities ai and bi.
You need to assign each city with an integer value from 1 to n, where each value can only be used once. The importance of a road is then defined as the sum of the values of the two cities it connects.
Return the maximum total importance of all roads possible after assigning the values optimally.
Example 1:
Input: n = 5, roads = [[0,1],[1,2],[2,3],[0,2],[1,3],[2,4]]
Output: 43
Explanation: The figure above shows the country and the assigned values of [2,4,5,3,1].
- The road (0,1) has an importance of 2 + 4 = 6.
- The road (1,2) has an importance of 4 + 5 = 9.
- The road (2,3) has an importance of 5 + 3 = 8.
- The road (0,2) has an importance of 2 + 5 = 7.
- The road (1,3) has an importance of 4 + 3 = 7.
- The road (2,4) has an importance of 5 + 1 = 6.
The total importance of all roads is 6 + 9 + 8 + 7 + 7 + 6 = 43.
It can be shown that we cannot obtain a greater total importance than 43.Example 2:
Input: n = 5, roads = [[0,3],[2,4],[1,3]]
Output: 20
Explanation: The figure above shows the country and the assigned values of [4,3,2,5,1].
- The road (0,3) has an importance of 4 + 5 = 9.
- The road (2,4) has an importance of 2 + 1 = 3.
- The road (1,3) has an importance of 3 + 5 = 8.
The total importance of all roads is 9 + 3 + 8 = 20.
It can be shown that we cannot obtain a greater total importance than 20.
Constraints:
2 <= n <= 5 * 1041 <= roads.length <= 5 * 104roads[i].length == 20 <= ai, bi <= n - 1ai != bi- There are no duplicate roads.
Approaches
2 approaches with complexity analysis and trade-offs.
The fundamental insight to solving this problem is to understand how the assignment of values to cities affects the total importance. The total importance is the sum of importances of all roads. If we expand this sum, we find that each city's assigned value contributes to the total sum as many times as its degree (the number of roads connected to it). Therefore, the total importance can be expressed as: Total Importance = Σ (value[i] * degree[i]) for all cities i.
To maximize this sum, we should employ a greedy strategy based on the rearrangement inequality: pair the largest values with the largest degrees. This means the city with the highest degree should be assigned the value n, the city with the second-highest degree gets n-1, and so on, down to the city with the lowest degree getting the value 1.
This approach implements this strategy by first calculating all city degrees, then sorting them, and finally calculating the total sum by pairing the sorted degrees with the values 1, 2, ..., n.
Algorithm
- Identify the Core Formula: The total importance of all roads is the sum of
value[u] + value[v]for every road(u, v). This can be rewritten as the sum ofvalue[city] * degree[city]for every city. The degree of a city is the number of roads connected to it. - Greedy Strategy: To maximize this sum, we must assign the largest values (from the set
{1, 2, ..., n}) to the cities with the highest degrees. This is based on the rearrangement inequality. - Implementation Steps:
- Create a
degreearray of sizento store the degree of each city. - Iterate through the
roadsarray. For each road[u, v], incrementdegree[u]anddegree[v]. - Sort the
degreearray in ascending order. This places the smallest degrees at the beginning and the largest degrees at the end. - Initialize a variable
totalImportanceto 0. - Iterate through the sorted
degreearray. Thei-th element (0-indexed) corresponds to thei-th smallest degree. Assign it thei-th smallest value, which isi + 1. - Add the product
sorted_degree[i] * (i + 1)tototalImportance. - Return
totalImportance.
- Create a
Walkthrough
import java.util.Arrays; class Solution { public long maximumImportance(int n, int[][] roads) { // Step 1 & 2: Calculate the degree of each city. // Use long for degree to avoid potential overflow in intermediate calculations, though int is sufficient for degree itself. long[] degree = new long[n]; for (int[] road : roads) { degree[road[0]]++; degree[road[1]]++; } // Step 3: Sort the degrees in ascending order. Arrays.sort(degree); // Step 4, 5, & 6: Calculate the total importance. // Assign values 1 to n to the sorted degrees. // The smallest degree gets value 1, second smallest gets 2, and so on. long totalImportance = 0; for (int i = 0; i < n; i++) { totalImportance += degree[i] * (i + 1); } // Step 7: Return the final result. return totalImportance; }}Complexity
Time
O(R + n log n), where `R` is the number of roads. It takes `O(R)` to compute the degrees. Sorting the `n` degrees takes `O(n log n)`. The final summation takes `O(n)`. The dominant factor is the sort.
Space
O(n) to store the `degree` array for `n` cities.
Trade-offs
Pros
The logic is straightforward and follows a common greedy pattern.
Relatively easy to implement using standard library sort functions.
Cons
The
O(n log n)sorting step is not the most optimal solution possible and can be a bottleneck ifnis very large.
This approach builds on the same greedy principle—pairing high degrees with high values—but optimizes the sorting step. A general-purpose comparison sort takes O(n log n) time. However, since the degrees are integers within a known range [0, n-1], we can use a more efficient, non-comparison-based sorting technique like Counting Sort. By counting the occurrences of each degree, we can effectively determine the sorted order of degrees in linear time.
We iterate through the possible degrees from smallest to largest. For each degree value, we assign the next available importance values (starting from 1) to all cities that have that degree. This avoids the O(n log n) bottleneck and leads to a more efficient linear time solution.
Algorithm
- Calculate Degrees: First, compute the degree of each city by iterating through the
roadsarray, similar to the previous approach. Store these in adegreearray. - Count Frequencies: Instead of sorting the
degreearray, create adegreeCountsarray of sizen.degreeCounts[d]will store the number of cities with degreed. Populate this by iterating through thedegreearray. - Calculate Importance Sum:
- Initialize
totalImportance = 0andvalue = 1. - Iterate through the
degreeCountsarray from degreed = 0ton-1. - For each degree
d, there aredegreeCounts[d]cities. These cities with the smallest degrees will be assigned the next available smallest values. - Use a nested loop: for each of the
degreeCounts[d]cities, addd * valuetototalImportanceand then incrementvalue. - After iterating through all degrees,
totalImportancewill hold the maximum possible sum.
- Initialize
Walkthrough
class Solution { public long maximumImportance(int n, int[][] roads) { // Step 1: Calculate the degree of each city. long[] degree = new long[n]; for (int[] road : roads) { degree[road[0]]++; degree[road[1]]++; } // Step 2: Count the frequency of each degree. // This is effectively a linear-time sorting method (Counting Sort). int[] degreeCounts = new int[n]; for (long d : degree) { // The degree of a city is at most n-1. degreeCounts[(int)d]++; } // Step 3: Calculate total importance using the counts. long totalImportance = 0; long value = 1; // Iterate through degrees from 0 to n-1. for (int d = 0; d < n; d++) { // For all cities that have degree 'd'. for (int i = 0; i < degreeCounts[d]; i++) { // Assign the next available value and add to the total importance. totalImportance += (long)d * value; value++; } } return totalImportance; }}Complexity
Time
O(R + n), where `R` is the number of roads. `O(R)` to compute degrees, `O(n)` to populate the `degreeCounts` array, and `O(n)` to calculate the final sum (the inner loop runs a total of `n` times across all iterations of the outer loop).
Space
O(n) to store the `degree` array and the `degreeCounts` array.
Trade-offs
Pros
Achieves optimal linear time complexity, making it very efficient.
Outperforms the sorting-based approach, especially for large values of
n.
Cons
The logic is slightly more involved than a direct sort, requiring an extra counting step.
Solutions
Solution
class Solution {public long maximumImportance(int n, int[][] roads) { int[] deg = new int[n]; for (int[] r : roads) { ++deg[r[0]]; ++deg[r[1]]; } Arrays.sort(deg); long ans = 0; for (int i = 0; i < n; ++i) { ans += (long)(i + 1) * deg[i]; } return ans; }}class Solution {public: long long maximumImportance(int n, vector<vector<int>> &roads) { vector<int> deg(n); for (auto &r : roads) { ++deg[r[0]]; ++deg[r[1]]; } sort(deg.begin(), deg.end()); long long ans = 0; for (int i = 0; i < n; ++i) ans += 1ll * (i + 1) * deg[i]; return ans; }};class Solution: def maximumImportance(self, n: int, roads: List[List[int]]) -> int: deg = [0] * n for a, b in roads: deg[a] += 1 deg[b] += 1 deg . sort() return sum(i * v for i, v in enumerate(deg, 1))Video walkthrough
Newsletter
One sharp idea, every week
System design and interview prep — short enough to finish.
No spam. Unsubscribe anytime.
Practice
Same difficulty — related problems to reinforce the pattern.