1. 程式人生 > >[洛谷P1268]樹的重量

[洛谷P1268]樹的重量

mem isdigit dig har ref ring ems 難點 http

原題傳送門

方法一

這道題是貪心。主要的難點在於合並路徑壓縮長度的策略。這裏采用的方法是讓一個個結點並入已經構建好的樹中,並記錄該結點接入樹的位置、接入樹到該結點的長度。模擬註意細節即可。

 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 }

方法二

將以上方法進行抽象簡化,不再模擬,直接維護統計即可。

[洛谷P1268]樹的重量