解题:USACO10MAR Great Cow Gather

题面

可以水水换根的,不过我是另一种做法:(按点权)找重心,事实上这是重心的一个性质

考虑换根的这个过程,当我们把点放在重心时,我们移动这个点有两种情况:

1.移动到最大的那个子树里

可以发现这个最大的子树的$size$不可能超过其余子树的$size$之和(最多是有两个重心的时候等于其他子树的$size$之和),不然你找的是假重心

2.移动到其他的子树里

显然这样只会让答案变差

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5 const int N=100005;
 6 long long dis[N],val[2*N],num[N],maxx[N],siz[N];
 7 int p[N],noww[2*N],goal[2*N],vis[N];
 8 long long ans,tot,t3,maxn=1e16;
 9 int n,c,t1,t2,cnt;
10 void link(int f,int t,long long v)
11 {
12     noww[++cnt]=p[f],p[f]=cnt;
13     goal[cnt]=t,val[cnt]=v;
14 }
15 void MARK(int nde,int fth)
16 {
17     siz[nde]=num[nde];
18     for(int i=p[nde];i;i=noww[i])
19         if(goal[i]!=fth)
20         {
21             MARK(goal[i],nde);
22             siz[nde]+=siz[goal[i]];
23             maxx[nde]=max(maxx[nde],siz[goal[i]]);
24         }
25     maxx[nde]=max(maxx[nde],tot-siz[nde]);
26     if(maxx[nde]<maxn) maxn=maxx[nde],c=nde;
27 }
28 void DFS(int nde,int fth)
29 {
30     for(int i=p[nde];i;i=noww[i])
31         if(goal[i]!=fth)
32         {
33             dis[goal[i]]=dis[nde]+val[i];
34             DFS(goal[i],nde);
35         }
36 }
37 int main()
38 {
39     scanf("%d",&n);
40     for(int i=1;i<=n;i++)
41         scanf("%lld",&num[i]),tot+=num[i];
42     for(int i=1;i<n;i++)
43     {
44         scanf("%d%d%lld",&t1,&t2,&t3);
45         link(t1,t2,t3),link(t2,t1,t3);
46     }
47     c=1; MARK(1,0); DFS(c,0); 
48     for(int i=1;i<=n;i++)
49         ans+=dis[i]*num[i];
50     printf("%lld",ans);
51     return 0;
52 }
View Code

 

posted @ 2018-10-11 08:11  Speranza_Leaf  阅读(154)  评论(0)    收藏  举报