您的位置:首页 > 产品设计 > UI/UE

Conquer a New Region HDU - 4424(带权并查集的dp)

2017-09-29 21:51 387 查看
The wheel of the history rolling forward, our king conquered a new region in a distant continent.

There are N towns (numbered from 1 to N) in this region connected by several roads. It’s confirmed that there is exact one route between any two towns. Traffic is important while controlled colonies are far away from the local country. We define the capacity C(i, j) of a road indicating it is allowed to transport at most C(i, j) goods between town i and town j if there is a road between them. And for a route between i and j, we define a value S(i, j) indicating the maximum traffic capacity between i and j which is equal to the minimum capacity of the roads on the route.

Our king wants to select a center town to restore his war-resources in which the total traffic capacities from the center to the other N - 1 towns is maximized. Now, you, the best programmer in the kingdom, should help our king to select this center.

Input

There are multiple test cases.

The first line of each case contains an integer N. (1 <= N <= 200,000)

The next N - 1 lines each contains three integers a, b, c indicating there is a road between town a and town b whose capacity is c. (1 <= a, b <= N, 1 <= c <= 100,000)

Output

For each test case, output an integer indicating the total traffic capacity of the chosen center town.

Sample Input

4

1 2 2

2 4 1

2 3 1

4

1 2 1

2 4 1

2 3 1

Sample Output

4

3

问题是如果首先确定了根,那么就很好求了,关键是不知道根,后来想了缩小规模看看,就知道根了,假设把两个子树合并了,那么根肯定是在两颗子树之一的地方,那么这个合成的树的路径必然经过这个连接边,到这就卡了,后来想如果这个边的权值是小与所有这两颗子树的边 ,那么当确定了一个根,那么连接到另一颗子树的值只能是这条最小边,所有想到把边排序了,从大到小合并,还有一个问题,合并了的新树的根一定是两颗子树的跟之一么,的确如此,因为假设选其他根,答案不会更大。

所有需要知道一个树的大小和维护这个树当前的答案,这么合并树,就是带权并查集,通过并查集实现dp的思想

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#define N 200005

using namespace std;
int pre
;
long long ans
;
int num
;
int  findd(int x)
{
return pre[x]==x?x:findd(pre[x]);
}
struct node
{
int x1,x2;
int w;
}edge
;
int n;
void init()
{
for(int i=1;i<=n;i++)
pre[i]=i;
for(int i=1;i<=n;i++)
num[i]=1;
memset(ans,0,sizeof(ans));
}
int cmp(node p1,node p2)
{
return p1.w>p2.w;
}
int main()
{
int x,y,w;
while(scanf("%d",&n)==1)
{
init();
for(int i=1;i<n;i++)
scanf("%d%d%d",&edge[i].x1,&edge[i].x2,&edge[i].w);
sort(edge+1,edge+n,cmp);
for(int i=1;i<n;i++)
{
int xx=findd(edge[i].x1);
int yy=findd(edge[i].x2);
ans[xx]+=(long long)edge[i].w*num[yy];
ans[yy]+=edge[i].w*num[xx];
if(ans[xx]>ans[yy])//选哪个点作为新树的根
{
num[xx]+=num[yy];
pre[yy]=xx;
}
else
{
num[yy]+=num[xx];
pre[xx]=yy;
}
}
printf("%lld\n",ans[findd(1)]);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: