如果某一列全为 \(0\),则该列表示的队伍会成为冠军。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| class Solution { public int findChampion(int[][] grid) { int n = grid.length; for (int j = 0; j < n; j++) { int cnt = 0; for (int i = 0; i < n && cnt == 0; i++) { cnt += grid[i][j]; } if (cnt == 0) { return j; } } return -1; } }
|
相当于判断入度为 \(0\) 的节点是否只有一个。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| class Solution { public int findChampion(int n, int[][] edges) { int[] in = new int[n]; for (var e : edges) { in[e[1]]++; } int ans = -1; for (int i = 0; i < n; i++) { if (in[i] == 0) { if (ans == -1) ans = i; else return -1; } } return ans; } }
|
树形 DP,要求最大分数,可以先求损失的最小分数,然后使用总分减去该分数即可。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| class Solution { public long maximumScoreAfterOperations(int[][] edges, int[] values) { int n = values.length; List<Integer>[] g = new List[n]; Arrays.setAll(g, k -> new ArrayList<>()); for (var e : edges) { int u = e[0], v = e[1]; g[u].add(v); g[v].add(u); } long ans = 0L; for (int x : values) { ans += x; } return ans - dfs(0, -1, g, values); } private long dfs(int x, int fa, List<Integer>[] g, int[] values) { if (g[x].size() == 1 && g[x].get(0) == fa) { return values[x]; } long res = 0L; for (int y : g[x]) { if (y != fa) { res += dfs(y, x, g, values); } } return Math.min(res, values[x]); } }
|
也可以直接正向做,对于每个节点有两种情况:选择当前节点,要求该节点的每个子树都是健康的;不选当前节点,该节点的所有子节点都可以选。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| class Solution { public long maximumScoreAfterOperations(int[][] edges, int[] values) { int n = values.length; List<Integer>[] g = new List[n]; Arrays.setAll(g, k -> new ArrayList<>()); for (var e : edges) { int u = e[0], v = e[1]; g[u].add(v); g[v].add(u); } long[] sum = new long[n]; return dfs(0, -1, g, values, sum); } private long dfs(int x, int fa, List<Integer>[] g, int[] values, long[] sum) { sum[x] = values[x]; if (g[x].size() == 1 && g[x].get(0) == fa) { return 0; } long dp0 = values[x], dp1 = 0; for (int y : g[x]) { if (y != fa) { dp0 += dfs(y, x, g, values, sum); dp1 += sum[y]; } } sum[x] += dp1; return Math.max(dp0, dp1); } }
|
离散化 + 树状数组优化 DP,直接看灵神代码吧。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
|
class Solution { public long maxBalancedSubsequenceSum(int[] nums) { int n = nums.length; int[] b = new int[n]; for (int i = 0; i < n; i++) { b[i] = nums[i] - i; } Arrays.sort(b); BIT t = new BIT(b.length + 1); for (int i = 0; i < n; i++) { int j = Arrays.binarySearch(b, nums[i] - i) + 1; long f = Math.max(t.preMax(j), 0) + nums[i]; t.update(j, f); } return t.preMax(b.length); } }
class BIT { private long[] tree;
public BIT(int n) { tree = new long[n]; Arrays.fill(tree, Long.MIN_VALUE); }
public void update(int i, long val) { while (i < tree.length) { tree[i] = Math.max(tree[i], val); i += i & -i; } }
public long preMax(int i) { long res = Long.MIN_VALUE; while (i > 0) { res = Math.max(res, tree[i]); i &= i - 1; } return res; } }
|