带权并查集咋过不了?
  • 板块CF1810E Monsters
  • 楼主Bob_Wang
  • 当前回复0
  • 已保存回复0
  • 发布时间2023/4/2 21:25
  • 上次更新2023/10/23 19:34:56
查看原帖
带权并查集咋过不了?
117395
Bob_Wang楼主2023/4/2 21:25
#include<cstdio>
#include<queue>
#define maxn 200005
using namespace std;

struct node
{
	int v,next;
}ed[maxn<<1];
int T,n,m;
int a[maxn],fa[maxn],cnt[maxn],vis[maxn],zero[maxn];
int tot,head[maxn];
priority_queue<pair<int,int> >que;

void add(int x,int y)
{
	tot++;
	ed[tot].v=y;
	ed[tot].next=head[x];
	head[x]=tot;
}

void clear()
{
	tot=0;
	for(int i=1;i<=n;++i)
	head[i]=vis[i]=0;
}

int find(int x)
{
	return (x==fa[x])?x:find(fa[x]);
}

void unionn(int x,int y)
{
	x=find(x);y=find(y);
	fa[x]=y;
	cnt[y]+=cnt[x];
}

int judge(int x,int y)
{
	x=find(x);y=find(y);
	return x==y;
}

void solve()
{
	int zo=0;
	for(int i=1;i<=n;++i)
	{
		if(a[i]==0)
		zero[++zo]=i;
	}
	for(int i=1;i<=zo;++i)
	{
		int x=zero[i];
		if(vis[x])
		continue;
		while(que.size())
		que.pop();
		vis[x]=1;
		for(int t=head[x];t;t=ed[t].next)
		{
			int y=ed[t].v;
			if(judge(x,y))
			continue;
			que.push(make_pair(-a[y],y));
		}//拓展
		while(que.size())
		{
			int y=que.top().second;
			que.pop();
			if(judge(x,y))
			continue;
			if(cnt[find(x)]<a[y])
			continue;
			vis[y]=1;
			unionn(x,y);
			for(int t=head[y];t;t=ed[t].next)
			{
				int z=ed[t].v;
				if(judge(x,z))
				continue;
				que.push(make_pair(-a[z],z));
			}
		}//往下走
	}
	if(cnt[find(1)]!=n)
	printf("No\n");
	else printf("Yes\n");
}

int main()
{
	scanf("%d",&T);
	while(T--)
	{
		scanf("%d%d",&n,&m);
		for(int i=1;i<=n;++i)
		{
			scanf("%d",&a[i]);
			fa[i]=i;
			cnt[i]=1;
		}
		for(int i=1;i<=m;++i)
		{
			int x,y;
			scanf("%d%d",&x,&y);
			add(x,y);
			add(y,x);
		}
		solve();
	    clear();
	}
	return 0;
}
2023/4/2 21:25
加载中...