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 }