Overflow in intermediate arithmetic
Wrong move: Temporary multiplications exceed integer bounds.
Usually fails on: Large inputs wrap around unexpectedly.
Fix: Use wider types, modular arithmetic, or rearranged operations.
Break down a hard problem into reliable checkpoints, edge-case handling, and complexity trade-offs.
You are given an undirected connected graph of n nodes, numbered from 0 to n - 1. Each node is connected to at most 2 other nodes.
The graph consists of m edges, represented by a 2D array edges, where edges[i] = [ai, bi] indicates that there is an edge between nodes ai and bi.
You have to assign a unique value from 1 to n to each node. The value of an edge will be the product of the values assigned to the two nodes it connects.
Your score is the sum of the values of all edges in the graph.
Return the maximum score you can achieve.
Example 1:
Input: n = 4, edges = [[0,1],[1,2],[2,3]]
Output: 23
Explanation:
The diagram above illustrates an optimal assignment of values to nodes. The sum of the values of the edges is: (1 * 3) + (3 * 4) + (4 * 2) = 23.
Example 2:
Input: n = 6, edges = [[0,3],[4,5],[2,0],[1,3],[2,4],[1,5]]
Output: 82
Explanation:
The diagram above illustrates an optimal assignment of values to nodes. The sum of the values of the edges is: (1 * 2) + (2 * 4) + (4 * 6) + (6 * 5) + (5 * 3) + (3 * 1) = 82.
Constraints:
1 <= n <= 5 * 104m == edges.length1 <= m <= nedges[i].length == 20 <= ai, bi < nai != biProblem summary: You are given an undirected connected graph of n nodes, numbered from 0 to n - 1. Each node is connected to at most 2 other nodes. The graph consists of m edges, represented by a 2D array edges, where edges[i] = [ai, bi] indicates that there is an edge between nodes ai and bi. You have to assign a unique value from 1 to n to each node. The value of an edge will be the product of the values assigned to the two nodes it connects. Your score is the sum of the values of all edges in the graph. Return the maximum score you can achieve.
Start with the most direct exhaustive search. That gives a correctness anchor before optimizing.
Pattern signal: Math · Greedy
4 [[0,1],[1,2],[2,3]]
6 [[0,3],[4,5],[2,0],[1,3],[2,4],[1,5]]
Source-backed implementations are provided below for direct study and interview prep.
// Accepted solution for LeetCode #3547: Maximum Sum of Edge Values in a Graph
class Solution {
public long maxScore(int n, int[][] edges) {
long ans = 0;
List<Integer>[] graph = new List[n];
List<Integer> cycleSizes = new ArrayList<>(); // components where all nodes have degree 2
List<Integer> pathSizes = new ArrayList<>(); // components that are not cycleSizes
boolean[] seen = new boolean[n];
Arrays.setAll(graph, i -> new ArrayList<>());
for (int[] edge : edges) {
final int u = edge[0];
final int v = edge[1];
graph[u].add(v);
graph[v].add(u);
}
for (int i = 0; i < n; ++i) {
if (seen[i])
continue;
List<Integer> component = getComponent(graph, i, seen);
final boolean allDegree2 = component.stream().allMatch(u -> graph[u].size() == 2);
if (allDegree2)
cycleSizes.add(component.size());
else if (component.size() > 1)
pathSizes.add(component.size());
}
for (final int cycleSize : cycleSizes) {
ans += calculateScore(n - cycleSize + 1, n, true);
n -= cycleSize;
}
Collections.sort(pathSizes, Collections.reverseOrder());
for (final int pathSize : pathSizes) {
ans += calculateScore(n - pathSize + 1, n, false);
n -= pathSize;
}
return ans;
}
private List<Integer> getComponent(List<Integer>[] graph, int start, boolean[] seen) {
List<Integer> component = new ArrayList<>(List.of(start));
seen[start] = true;
for (int i = 0; i < component.size(); ++i) {
final int u = component.get(i);
for (final int v : graph[u]) {
if (seen[v])
continue;
component.add(v);
seen[v] = true;
}
}
return component;
}
private long calculateScore(int left, int right, boolean isCycle) {
Deque<Long> window = new ArrayDeque<>();
window.offerLast((long) right);
window.offerLast((long) right);
long score = 0;
for (int value = right - 1; value >= left; --value) {
final long windowValue = window.pollFirst();
score += windowValue * value;
window.offerLast((long) value);
}
return score + window.peekFirst() * window.peekLast() * (isCycle ? 1 : 0);
}
}
// Accepted solution for LeetCode #3547: Maximum Sum of Edge Values in a Graph
package main
import (
"fmt"
"math"
"math/bits"
"slices"
)
// https://space.bilibili.com/206214
func maxScore(n int, edges [][]int) int64 {
ans := (n*n*2 + n*5 - 6) * (n - 1) / 6
if n == len(edges) { // 环
ans += 2
}
return int64(ans)
}
func maxScoreOld(n int, edges [][]int) int64 {
g := make([][]int, n)
for _, e := range edges {
x, y := e[0], e[1]
g[x] = append(g[x], y)
g[y] = append(g[y], x)
}
var cycle, chain []int
var cntV, cntE int
vis := make([]bool, n)
var dfs func(int)
dfs = func(x int) {
vis[x] = true
cntV++
cntE += len(g[x])
for _, y := range g[x] {
if !vis[y] {
dfs(y)
}
}
}
for i, b := range vis {
if b {
continue
}
cntV, cntE = 0, 0
dfs(i)
if cntV*2 == cntE { // 环
cycle = append(cycle, cntV)
} else if cntE > 0 { // 链,但不考虑孤立点
chain = append(chain, cntV)
}
}
ans := 0
cur := n
f := func(sz int, isCycle bool) {
l, r := cur-sz+1, cur
for i := l; i < r-1; i++ {
ans += i * (i + 2)
}
ans += r * (r - 1)
if isCycle {
ans += l * (l + 1)
}
cur -= sz
}
slices.Sort(cycle)
for _, sz := range cycle {
f(sz, true)
}
slices.SortFunc(chain, func(a, b int) int { return b - a })
for _, sz := range chain {
f(sz, false)
}
return int64(ans)
}
// 保证 size[i] >= 2, n >= sum(size)
func chainGreedy(size []int, n int) (ans int) {
slices.Sort(size)
tot := 0
for _, v := range size {
tot += v
}
low := n - tot + 1
a := make([][]int, len(size))
for i, sz := range size {
a[i] = make([]int, sz)
a[i][0] = low
low++
a[i][sz-1] = low
low++
}
for p, sz := range size {
i, j := 1, sz-2
row := a[p]
for i <= j {
row[i] = low
low++
i++
if i > j {
break
}
row[j] = low
low++
j--
}
}
for _, row := range a {
for i := 1; i < len(row); i++ {
v, w := row[i-1], row[i]
ans += v * w
}
}
return
}
func runAC(size []int, n int) (ans int) {
size = slices.Clone(size)
tot := 0
ban := make([]bool, n+1)
ban[0] = true
for _, v := range size {
tot += v
ban[tot] = true
}
base := n - tot + 1
dp := make([][]int, 1<<tot)
for i := range dp {
dp[i] = make([]int, tot)
for j := range dp[i] {
dp[i][j] = math.MinInt
}
}
var f func(int, int) int
f = func(left, pre int) (res int) {
if left < 0 {
return
}
dv := &dp[left][pre]
if *dv != math.MinInt {
return *dv
}
defer func() { *dv = res }()
choose := tot - bits.OnesCount(uint(left))
for _s := uint(left); _s > 0; _s &= _s - 1 {
p := bits.TrailingZeros(_s)
r := f(left^1<<p, p)
if !ban[choose] {
r += (p + base) * (pre + base)
}
res = max(res, r)
}
return
}
ans = f(1<<tot-1, 0)
return
}
func main() {
fmt.Println(chainGreedy([]int{3, 4}, 11))
fmt.Println(runAC([]int{3, 4}, 11))
}
# Accepted solution for LeetCode #3547: Maximum Sum of Edge Values in a Graph
class Solution:
def maxScore(self, n: int, edges: list[list[int]]) -> int:
ans = 0
graph = [[] for _ in range(n)]
cycleSizes = [] # components where all nodes have degree 2
pathSizes = [] # components that are not cycleSizes
seen = set()
for u, v in edges:
graph[u].append(v)
graph[v].append(u)
for i in range(n):
if i in seen:
continue
component = self._getComponent(graph, i, seen)
if all(len(graph[u]) == 2 for u in component):
cycleSizes.append(len(component))
elif len(component) > 1:
pathSizes.append(len(component))
for cycleSize in cycleSizes:
ans += self._calculateScore(n - cycleSize + 1, n, True)
n -= cycleSize
for pathSize in sorted(pathSizes, reverse=True):
ans += self._calculateScore(n - pathSize + 1, n, False)
n -= pathSize
return ans
def _getComponent(
self,
graph: list[list[int]],
start: int,
seen: set[int],
) -> list[int]:
component = [start]
seen.add(start)
for u in component:
for v in graph[u]:
if v in seen:
continue
component.append(v)
seen.add(v)
return component
def _calculateScore(self, left: int, right: int, isCycle: bool) -> int:
window = collections.deque([right, right])
score = 0
for value in range(right - 1, left - 1, -1):
windowValue = window.popleft()
score += windowValue * value
window.append(value)
return score + window[0] * window[1] * isCycle
// Accepted solution for LeetCode #3547: Maximum Sum of Edge Values in a Graph
// Rust example auto-generated from java reference.
// Replace the signature and local types with the exact LeetCode harness for this problem.
impl Solution {
pub fn rust_example() {
// Port the logic from the reference block below.
}
}
// Reference (java):
// // Accepted solution for LeetCode #3547: Maximum Sum of Edge Values in a Graph
// class Solution {
// public long maxScore(int n, int[][] edges) {
// long ans = 0;
// List<Integer>[] graph = new List[n];
// List<Integer> cycleSizes = new ArrayList<>(); // components where all nodes have degree 2
// List<Integer> pathSizes = new ArrayList<>(); // components that are not cycleSizes
// boolean[] seen = new boolean[n];
// Arrays.setAll(graph, i -> new ArrayList<>());
//
// for (int[] edge : edges) {
// final int u = edge[0];
// final int v = edge[1];
// graph[u].add(v);
// graph[v].add(u);
// }
//
// for (int i = 0; i < n; ++i) {
// if (seen[i])
// continue;
// List<Integer> component = getComponent(graph, i, seen);
// final boolean allDegree2 = component.stream().allMatch(u -> graph[u].size() == 2);
// if (allDegree2)
// cycleSizes.add(component.size());
// else if (component.size() > 1)
// pathSizes.add(component.size());
// }
//
// for (final int cycleSize : cycleSizes) {
// ans += calculateScore(n - cycleSize + 1, n, true);
// n -= cycleSize;
// }
//
// Collections.sort(pathSizes, Collections.reverseOrder());
//
// for (final int pathSize : pathSizes) {
// ans += calculateScore(n - pathSize + 1, n, false);
// n -= pathSize;
// }
//
// return ans;
// }
//
// private List<Integer> getComponent(List<Integer>[] graph, int start, boolean[] seen) {
// List<Integer> component = new ArrayList<>(List.of(start));
// seen[start] = true;
// for (int i = 0; i < component.size(); ++i) {
// final int u = component.get(i);
// for (final int v : graph[u]) {
// if (seen[v])
// continue;
// component.add(v);
// seen[v] = true;
// }
// }
// return component;
// }
//
// private long calculateScore(int left, int right, boolean isCycle) {
// Deque<Long> window = new ArrayDeque<>();
// window.offerLast((long) right);
// window.offerLast((long) right);
// long score = 0;
// for (int value = right - 1; value >= left; --value) {
// final long windowValue = window.pollFirst();
// score += windowValue * value;
// window.offerLast((long) value);
// }
// return score + window.peekFirst() * window.peekLast() * (isCycle ? 1 : 0);
// }
// }
// Accepted solution for LeetCode #3547: Maximum Sum of Edge Values in a Graph
// Auto-generated TypeScript example from java.
function exampleSolution(): void {
}
// Reference (java):
// // Accepted solution for LeetCode #3547: Maximum Sum of Edge Values in a Graph
// class Solution {
// public long maxScore(int n, int[][] edges) {
// long ans = 0;
// List<Integer>[] graph = new List[n];
// List<Integer> cycleSizes = new ArrayList<>(); // components where all nodes have degree 2
// List<Integer> pathSizes = new ArrayList<>(); // components that are not cycleSizes
// boolean[] seen = new boolean[n];
// Arrays.setAll(graph, i -> new ArrayList<>());
//
// for (int[] edge : edges) {
// final int u = edge[0];
// final int v = edge[1];
// graph[u].add(v);
// graph[v].add(u);
// }
//
// for (int i = 0; i < n; ++i) {
// if (seen[i])
// continue;
// List<Integer> component = getComponent(graph, i, seen);
// final boolean allDegree2 = component.stream().allMatch(u -> graph[u].size() == 2);
// if (allDegree2)
// cycleSizes.add(component.size());
// else if (component.size() > 1)
// pathSizes.add(component.size());
// }
//
// for (final int cycleSize : cycleSizes) {
// ans += calculateScore(n - cycleSize + 1, n, true);
// n -= cycleSize;
// }
//
// Collections.sort(pathSizes, Collections.reverseOrder());
//
// for (final int pathSize : pathSizes) {
// ans += calculateScore(n - pathSize + 1, n, false);
// n -= pathSize;
// }
//
// return ans;
// }
//
// private List<Integer> getComponent(List<Integer>[] graph, int start, boolean[] seen) {
// List<Integer> component = new ArrayList<>(List.of(start));
// seen[start] = true;
// for (int i = 0; i < component.size(); ++i) {
// final int u = component.get(i);
// for (final int v : graph[u]) {
// if (seen[v])
// continue;
// component.add(v);
// seen[v] = true;
// }
// }
// return component;
// }
//
// private long calculateScore(int left, int right, boolean isCycle) {
// Deque<Long> window = new ArrayDeque<>();
// window.offerLast((long) right);
// window.offerLast((long) right);
// long score = 0;
// for (int value = right - 1; value >= left; --value) {
// final long windowValue = window.pollFirst();
// score += windowValue * value;
// window.offerLast((long) value);
// }
// return score + window.peekFirst() * window.peekLast() * (isCycle ? 1 : 0);
// }
// }
Use this to step through a reusable interview workflow for this problem.
Try every possible combination of choices. With n items each having two states (include/exclude), the search space is 2ⁿ. Evaluating each combination takes O(n), giving O(n × 2ⁿ). The recursion stack or subset storage uses O(n) space.
Greedy algorithms typically sort the input (O(n log n)) then make a single pass (O(n)). The sort dominates. If the input is already sorted or the greedy choice can be computed without sorting, time drops to O(n). Proving greedy correctness (exchange argument) is harder than the implementation.
Review these before coding to avoid predictable interview regressions.
Wrong move: Temporary multiplications exceed integer bounds.
Usually fails on: Large inputs wrap around unexpectedly.
Fix: Use wider types, modular arithmetic, or rearranged operations.
Wrong move: Locally optimal choices may fail globally.
Usually fails on: Counterexamples appear on crafted input orderings.
Fix: Verify with exchange argument or monotonic objective before committing.