[Atcoder NIKKEI Contest 2019]E.Weights on Vertices and Edges(并查集)

即将退役前把之前咕掉的题解补上

题面

Score: 800800800 points
There is a connected undirected graph with NNN vertices and MMM edges. The vertices are numbered 111 to NNN, and the edges are numbered 111 to MMM.
Also, each of these vertices and edges has a specified weight. Vertex iii has a weight of
XiX_iXi; Edge iii has a weight of YiY_iYi and connects Vertex AiA_iAi and BiB_iBi.
We would like to remove zero or more edges so that the following condition is satisfied:

For each edge that is not removed, the sum of the weights of the vertices in the connected component containing that edge, is greater than or equal to the weight of that edge.

Find the minimum number of edges that need to be removed.
1≤N,M≤1051≤N,M≤10^51N,M105

题解

考试的时候看起来好难的样子,就弃掉颓废去了…

首先显然我们每次删边算联通块是不现实的,因此我们需要计算保留下来的边。
这样我们就可以将边依次加入到图中,算联通块用并查集实现,加入到图中的所有边就是保留下来的边。
考虑到联通块的重量显然是递增的,那么这样,可以接受的边也就越来越多。
那么我们可以尝试按边的重量从小到大排序加入。
考虑新加入一条合并两个联通块的边uuu,vvv,(u≠v)(u≠v)(u̸=v)
1.若总重量超过这条边,显然是可行的。
2.如果没有超过,可以用一个cntcntcnt数组暂时记一下,等到再次出现了第一种情况,显然已经达到要求,那么我们就可以将它加进去了。
对于u=vu=vu=v的情况,我们也可以用类似的方法解决。
由于时间问题,详细请参考代码。
O(nα(n))O(n α(n))O(nα(n))

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
#define MAXN 100000 
#define LL long long
int n,m,ans;
LL w[MAXN+5];
int fa[MAXN+5],cnt[MAXN+5];
struct edge{
	int u,v,w;
}a[MAXN+5];
bool cmp(edge s1,edge s2){return s1.w<s2.w;}
int xfind(int x){return (fa[x]==x)?x:fa[x]=xfind(fa[x]);}
int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)
	{scanf("%lld",&w[i]);fa[i]=i;}
	for(int i=1;i<=m;i++)
		scanf("%d%d%d",&a[i].u,&a[i].v,&a[i].w);
	sort(a+1,a+m+1,cmp);
	for(int i=1;i<=m;i++)
	{
		int x=xfind(a[i].u),y=xfind(a[i].v);
		if(x!=y)
		{
			w[x]+=w[y];
			cnt[x]+=cnt[y];
			w[y]=0,cnt[y]=0;
			fa[y]=x;
		}
		cnt[x]++;
		if(w[x]>=a[i].w)
		{
			ans+=cnt[x];
			cnt[x]=0;
		}
	}
	printf("%d",m-ans);
}

转载于:https://www.cnblogs.com/Panda-hu/p/11145733.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值