HDU-4424 Conquer a New Region(并查集)

探讨了在给定的树形图中找到一个点,该点与其他所有点间路径中最小边容量之和最大。通过优先处理大边权并采用并查集策略,逐步合并节点集以求解。

题意:

给定n个点的树形图,一个点u到一个点v的路径中边的容量最小的一条边称为S(u, v),让你寻找一个点造成它到其它n-1个点的S(..)加和最大,输出最大加和。

思路:

由于边权较小的边会限制边权较大的边,所以我们先处理边权较大的边,初始时把n个点作为n个集合,然后利用并查集不断合并两个不连通的点集。由于我们之前用较大边权的边形成集合,所以我们对于当前边的两点,去合并它们分别所在的集合,由于它是到此刻最小的边权,所以把一个集合合并至另一个集合就是一个集合的点个数*当前边权w再加入到另一个集合的总权和中。所以进行比较一下然后确定哪个集合加入哪个集合会造成更优从而确定新的集合,这样肯定是正确的,因为之后小的边要加入这个集合中,必定不会使此时的结果更优了。

代码:

#include <bits/stdc++.h>
#define ll long long
using namespace std;

const int maxn = 2e5+5;
struct node
{
	int u, v, w;
	bool operator<(const node k)const
	{
		return w < k.w;
	}
};
ll ans[maxn];
int num[maxn], f[maxn];
int n;
priority_queue<node> q;
int getF(int x)
{
	if(x == f[x]) return x;
	f[x] = getF(f[x]);
	return f[x];
}
int main()
{
	while(~scanf("%d", &n))
	{
		for(int i = 1; i <= n; ++i)
		f[i] = i, num[i] = 1, ans[i] = 0;
		for(int i = 1; i < n; ++i)
		{
			int u, v, w;
			scanf("%d %d %d", &u, &v, &w);
			q.push((node){u, v, w});
		}
		while(!q.empty())
		{
			node top = q.top(); q.pop();
			int u = top.u, v = top.v, w = top.w;
			int fu = getF(u), fv = getF(v);
			if(ans[fu]+1ll*num[fv]*w > ans[fv]+1ll*num[fu]*w)
			{
				ans[fu] += 1ll*num[fv]*w;
				num[fu] += num[fv];
				f[fv] = fu;
			}
			else
			{
				ans[fv] += 1ll*num[fu]*w;
				num[fv] += num[fu];
				f[fu] = fv;
			}
		}
		printf("%lld\n", ans[getF(1)]);
	}
	return 0ll;
}


继续加油~

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值