5776. 【NOIP2008模拟】小x游世界树
(File IO): input:yggdrasil.in output:yggdrasil.out
Time Limits: 1500 ms Memory Limits: 262144 KB Detailed Limits
Goto ProblemSet做法:其实并不是每个点都要建一次树,我们可以在一个点为整棵树的根节点时,以它的答案来更新它的儿子节点的答案,这样实际上只会涉及一条边贡献的改变。
代码如下:
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 #define LL long long 5 #define N 1000007 6 using namespace std; 7 struct edge 8 { 9 LL to, next, w; 10 }e[N * 2]; 11 LL zs[N], n, a[N], ls[N * 2], ans, root, site, cnt; 12 bool v[N]; 13 14 void add(LL x, LL y, LL z) 15 { 16 e[++cnt].to = y; 17 e[cnt].next = ls[x]; 18 e[cnt].w = z; 19 ls[x] = cnt; 20 } 21 22 void dfs(LL x, LL sum) 23 { 24 root += sum; 25 for (int i = ls[x]; i; i = e[i].next) 26 { 27 if (v[e[i].to]) continue; 28 v[e[i].to] = 1; 29 dfs(e[i].to, sum + (e[i].w - a[x])); 30 zs[x] += zs[e[i].to]; 31 } 32 zs[x]++; 33 } 34 35 void find(LL x, LL sum) 36 { 37 if (sum < ans) 38 { 39 ans = sum; 40 site = x; 41 } 42 else if (sum == ans) site = min(site, x); 43 for (int i = ls[x]; i; i = e[i].next) 44 { 45 if (v[e[i].to]) continue; 46 v[e[i].to] = 1; 47 find(e[i].to, sum + (n - zs[e[i].to]) * (e[i].w - a[e[i].to])- zs[e[i].to] * (e[i].w - a[x])); 48 } 49 } 50 51 int main() 52 { 53 freopen("yggdrasil.in", "r", stdin); 54 freopen("yggdrasil.out", "w", stdout); 55 scanf("%lld", &n); 56 for (int i = 1; i <= n; i++) 57 scanf("%lld", &a[i]); 58 for (int i = 1; i <= n - 1; i++) 59 { 60 LL x, y, z; 61 scanf("%lld%lld%lld", &x, &y, &z); 62 add(x, y, z); 63 add(y, x, z); 64 } 65 v[1] = 1; 66 dfs(1, 0); 67 ans = root; 68 site = 1; 69 memset(v, 0, sizeof(v)); 70 v[1] = 1; 71 find(1, root); 72 printf("%lld ", site); 73 printf("%lld", ans); 74 }