[洛谷P1268]树的重量

原题传送门

方法一

这道题是贪心。主要的难点在于合并路径压缩长度的策略。这里采用的方法是让一个个结点并入已经构建好的树中,并记录该结点接入树的位置、接入树到该结点的长度。模拟注意细节即可。

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <algorithm>
 5 
 6 using namespace std;
 7 
 8 #define re register
 9 #define rep(i, a, b) for (re int i = a; i <= b; ++i)
10 #define repd(i, a, b) for (re int i = a; i >= b; --i)
11 #define maxx(a, b) a = max(a, b);
12 #define minn(a, b) a = min(a, b);
13 #define LL long long
14 #define inf (1 << 30)
15 
16 inline int read() {
17     int w = 0, f = 1; char c = getchar();
18     while (!isdigit(c)) f = c == '-' ? -1 : f, c = getchar();
19     while (isdigit(c)) w = (w << 3) + (w << 1) + (c ^ '0'), c = getchar();
20     return w * f;
21 }
22 
23 const int maxn = 30 + 5, maxw = 100 + 5;
24 
25 int N, M[maxn][maxn], link[maxn][maxw], l[maxn], ans;
26 
27 int main() {
28     while (N = read()) {
29         memset(M, 0, sizeof(M));
30         memset(link, 0, sizeof(link));
31         memset(l, 0, sizeof(l));
32         rep(i, 1, N-1)
33             rep(j, i+1, N)
34                 M[i][j] = M[j][i] = read();
35         l[2] = M[1][2];
36         rep(i, 3, N) {
37             l[i] = M[1][i];
38             int p = 2, q = 0;
39             while (1) {
40                 int del = min((l[i] + l[p] - q - M[i][p]) >> 1, l[i]);
41                 q += del; l[i] -= del;
42                 if (link[p][q]) p = link[p][q], q = 0; else break;
43             }
44             while (link[p][q]) p = link[p][q], q = 0;
45             link[p][q] = i;
46         }
47         ans = 0;
48         rep(i, 2, N) ans += l[i];
49         printf("%d\n", ans);
50     }
51 
52     return 0;
53 }

方法二

将以上方法进行抽象简化,不再模拟,直接维护统计即可。

猜你喜欢

转载自www.cnblogs.com/ac-evil/p/10322307.html