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 }
View Code

 

 

posted @ 2013-06-10 21:32  ihge2k  阅读(516)  评论(0编辑  收藏  举报