UVa 1664 Conquer a New Region(并查集)

https://vjudge.net/problem/UVA-1664

题意:

n个城市形成一棵树,每条边有权值C(i,j)。任意两个点的容量S(i,j)定义为i与j唯一通路上容量的最小值。找一个点,使得它到其他所有点的容量之和最大。

 

思路:

做法有点类似于最小生成树的Kruskal算法。

先将边按权值从大到小排列,每次新加入一条边,检查边两段A和B所处并查集的根结点,并通过计算得出谁作为中心点时容量更大。计算过程中需要维护一些东西,sum[i]是以i为中心时的容量之和,cnt[i]是以i为根结点时树的结点个数(初始时都是为1)。

下面举例说明:

1 2  2

2 4  1

2 3  1

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<string>
 4 #include<cstring>
 5 using namespace std;
 6 
 7 const int maxn = 200000 + 5;
 8 
 9 struct node
10 {
11     int u, v;
12     int w;
13 }t[maxn];
14 
15 int p[maxn];
16 long long sum[maxn];
17 long long cnt[maxn];
18 int n;
19 long long ans;
20 
21 bool cmp(node a, node b)
22 {
23     return a.w > b.w;
24 }
25 
26 int find(int x)
27 {
28     return x == p[x] ? x : find(p[x]);
29 }
30 
31 void solve()
32 {
33     ans = 0;
34     for (int i = 0; i <= n; i++)   { p[i] = i; sum[i] = 0; cnt[i] = 1; }
35     sort(t, t + n - 1 , cmp);
36     for (int i = 0; i < n - 1; i++)
37     {
38         int x = find(t[i].u);
39         int y = find(t[i].v);
40         long long sum1 = sum[x] + cnt[y] * t[i].w;
41         long long sum2 = sum[y] + cnt[x] * t[i].w;
42         if (sum1>sum2)
43         {
44             p[y] = x;
45             cnt[x] += cnt[y];
46             sum[x] = sum1;
47             ans = sum[x];
48         }
49         else
50         {
51             p[x] = y;
52             cnt[y] += cnt[x];
53             sum[y] = sum2;
54             ans = sum[y];
55         }
56     }
57     printf("%lld\n", ans);
58 }
59 
60 int main()
61 {
62     //freopen("D:\\txt.txt", "r", stdin);
63     while (~scanf("%d", &n))
64     {
65         for (int i = 0; i < n - 1; i++)
66             scanf("%d%d%d", &t[i].u, &t[i].v, &t[i].w);
67         solve();
68     }
69     return 0;
70 }

 

转载于:https://www.cnblogs.com/zyb993963526/p/6637947.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值