zoj 3659 第37届ACM/ICPC 长春赛区现场赛E题 (并查集)

题意:给出一棵树,找出一个点,求出所有点到这个点的权值和最大,权值为路径上所有边权的最小值。

用神奇的并查集,把路按照权值从大到小排序,然后用类似Kruskal的方法不断的加入边。 对于要加入的一条路,这条路连接这城市x和y,x所在的集合为A, y所在的集合为B, 可以确定A,B集合内的所有路都比当前这条路的权值大。如果让集合B加入集合A,就是让中心城市位于集合A,那么可以确定这两个集合合并之后的总权值为: A的权值总和+B的数量*当前这条路的权值。同样算出让集合B加入集合A的情况,取两者合并后权值大的进行合并。

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<algorithm>
 4 #include<cstring>
 5 #include<cmath>
 6 #include<queue>
 7 #include<map>
 8 using namespace std;
 9 #define MOD 1000000007
10 const double eps=1e-5;
11 #define cl(a) memset(a,0,sizeof(a))
12 #define ts printf("*****\n");
13 const int MAXN=200005;
14 int n,m,tt;
15 int F[MAXN];
16 struct Edge
17 {
18     int a,b,c;
19     void input()
20     {
21         scanf("%d%d%d",&a,&b,&c);
22     }
23 }edge[MAXN];
24 int find(int x)
25 {
26     if(F[x]==-1)    return x;
27     return F[x]=find(F[x]);
28 }
29 struct Node
30 {
31     long long sum;
32     long long num;
33 }node[MAXN];
34 bool cmp(Edge a,Edge b)
35 {
36     return a.c>b.c;
37 }
38 int main()
39 {
40     int i,j,k;
41     #ifndef ONLINE_JUDGE
42     freopen("1.in","r",stdin);
43     #endif
44     while(scanf("%d",&n)!=EOF)
45     {
46         for(i=1;i<n;i++)   edge[i].input();
47         sort(edge+1,edge+n,cmp);
48         for(i=1;i<=n;i++)
49         {
50             node[i].num=1;
51             node[i].sum=0;
52             F[i]=-1;
53         }
54         for(i=1;i<n;i++)
55         {
56             int a1=edge[i].a;
57             int a2=edge[i].b;
58             int t1=find(a1);
59             int t2=find(a2);
60             if(node[t1].sum+(long long)node[t2].num*edge[i].c<node[t2].sum+(long long)node[t1].num*edge[i].c)
61             {
62                 F[t1]=t2;   //t2作为被选择的点
63                 node[t2].num+=node[t1].num;
64                 node[t2].sum+=(long long)edge[i].c*node[t1].num;
65             }
66             else
67             {
68                 F[t2]=t1;
69                 node[t1].num+=node[t2].num;
70                 node[t1].sum+=(long long)edge[i].c*node[t2].num;
71             }
72         }
73         printf("%lld\n",node[find(1)].sum);
74     }
75 }

 

转载于:https://www.cnblogs.com/cnblogs321114287/p/4430425.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值