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

 

 

你可能感兴趣的:(HDU)