一道非常好的构造题。
我反正是一点思路都没有,最后还是看了题解。
假如n = 2,那么树的重量就是di,j。
然后n = 3,画一个图:,则重量=(d1,3 + d2,3 - d1,2) / 2。
n = 4同理:,加上的应该是(d1,4 + dj,4 - d1,j) / 2 (j < 4)的最小值,这里面j = 3。因为如果不是最小值的话,比如 j = 2,那么多加了一段图中红色的部分。
依次类推,树的重量就构造出来了。
1 #include<cstdio> 2 #include<iostream> 3 #include<cmath> 4 #include<algorithm> 5 #include<cstring> 6 #include<cstdlib> 7 #include<cctype> 8 #include<vector> 9 #include<stack> 10 #include<queue> 11 using namespace std; 12 #define enter puts("") 13 #define space putchar(' ') 14 #define Mem(a, x) memset(a, x, sizeof(a)) 15 #define rg register 16 typedef long long ll; 17 typedef double db; 18 const int INF = 0x3f3f3f3f; 19 const db eps = 1e-8; 20 const int maxn = 35; 21 inline ll read() 22 { 23 ll ans = 0; 24 char ch = getchar(), last = ' '; 25 while(!isdigit(ch)) last = ch, ch = getchar(); 26 while(isdigit(ch)) ans = (ans << 1) + (ans << 3) + ch - '0', ch = getchar(); 27 if(last == '-') ans = -ans; 28 return ans; 29 } 30 inline void write(ll x) 31 { 32 if(x < 0) x = -x, putchar('-'); 33 if(x >= 10) write(x / 10); 34 putchar(x % 10 + '0'); 35 } 36 37 int n, G[maxn][maxn]; 38 39 int main() 40 { 41 while(scanf("%d", &n) && n) 42 { 43 Mem(G, 0); 44 for(int i = 1; i <= n; ++i) 45 for(int j = i + 1; j <= n; ++j) G[i][j] = G[j][i] = read(); 46 int ans = 0; 47 for(int i = 2; i <= n; ++i) 48 { 49 int Min = INF; 50 for(int j = 1; j < i; ++j) Min = min(Min, (G[1][i] + G[j][i] - G[1][j]) >> 1); 51 ans += Min; 52 } 53 write(ans), enter; 54 } 55 return 0; 56 }