[洛谷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 }
方法二
将以上方法进行抽象简化,不再模拟,直接统计即可。
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; 24 25 int n, e[maxn][maxn], ans; 26 27 int main() { 28 while (n = read()) { 29 ans = 0; 30 rep(i, 1, n-1) 31 rep(j, i+1, n) 32 e[i][j] = e[j][i] = read(); 33 rep(i, 2, n) { 34 int l = INF; 35 rep(j, 1, i-1) 36 l = min(l, e[1][i] - ((e[1][i] + e[1][j] - e[i][j]) >> 1)); 37 ans += l; 38 } 39 printf("%d\n", ans); 40 } 41 42 return 0; 43 }