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
", 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