hdu 4424
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4424
题意:给你一颗树,树中每条边有一权值c,对于从i节点到j节点的路径,其权值定义为该路径上边权值的最小值,于是问找到一个中心点,使得从该点到其他节点的路径权值和最大,求该最大值。
思路;要使得权值和最大,容易想到对边进行从大到小排序,用一个sum来记录权值,cnt来记录节点个数,然后每次合并时取权值和较大的那个即可。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 #define MAXN 200200 7 typedef long long LL; 8 int parent[MAXN]; 9 LL sum[MAXN]; 10 int cnt[MAXN]; 11 struct Edge{ 12 int u,v,w; 13 }edge[MAXN]; 14 int n; 15 16 void Initiate() 17 { 18 memset(sum,0,(n+2)*sizeof(sum[0])); 19 for(int i=0;i<=n;i++){ 20 parent[i]=i; 21 cnt[i]=1; 22 } 23 } 24 25 int Find(int x) 26 { 27 if(x==parent[x]) 28 return x; 29 parent[x]=Find(parent[x]); 30 return parent[x]; 31 } 32 33 void Union(int r1,int r2,LL w) 34 { 35 parent[r1]=r2; 36 cnt[r2]+=cnt[r1]; 37 sum[r2]+=w; 38 } 39 40 int cmp(const Edge &p,const Edge &q) 41 { 42 return p.w>q.w; 43 } 44 45 int main() 46 { 47 // freopen("1.txt","r",stdin); 48 while(~scanf("%d",&n)) 49 { 50 Initiate(); 51 for(int i=0;i<n-1;i++){ 52 scanf("%d%d%d",&edge[i].u,&edge[i].v,&edge[i].w); 53 } 54 sort(edge,edge+n-1,cmp); 55 for(int i=0;i<n-1;i++){ 56 int r1=Find(edge[i].u); 57 int r2=Find(edge[i].v); 58 LL w=(LL)edge[i].w; 59 LL tmp1=cnt[r2]*w+sum[r1]; 60 LL tmp2=cnt[r1]*w+sum[r2]; 61 if(tmp1>tmp2){ 62 Union(r2,r1,tmp1-sum[r1]); 63 }else 64 Union(r1,r2,tmp2-sum[r2]); 65 } 66 printf("%I64d\n",sum[Find(1)]); 67 } 68 return 0; 69 }