BZOJ1116&&洛谷P3465 [POI2008]CLO-Toll

并查集+dfs定向

我们根据两个点是不是在同一个连通块来连边,通过并查集判环,显然只有图中存在环的时候,才会满足题意

代码(因为BZOJ并不要求输出方案,所以洛谷的输出方案看看就好,主要是并查集判环)

//By AcerMo
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int M=100050;
int n,m,cnt;
int fa[M];
bool vis[M],jud[M],in[M];
int to[M],head[M],nxt[M],ans[M];
inline int read()
{
	int x=0;char ch=getchar();
	while (ch>'9'||ch<'0') ch=getchar();
	while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
	return x;
}
inline void add(int x,int y)
{
	to[++cnt]=y;nxt[cnt]=head[x];head[x]=cnt;
	to[++cnt]=x;nxt[cnt]=head[y];head[y]=cnt;
	return ;
}
inline int find(int x)
{
	if (x!=fa[x]) return fa[x]=find(fa[x]);
	return x;
}
inline int unionn(int a,int b)
{
	if (a==b&&!vis[a]) return vis[a]=1,1;
	if (a==b&&vis[a]) return 0;
	fa[a]=b;vis[b]=(vis[a]|vis[b]);
	return 1;
}
inline void dfs(int x,int fat)
{
	in[x]=1;
	for (int i=head[x];i;i=nxt[i])
	if (to[i]!=fat)
	{
		if (!in[to[i]]) dfs(to[i],x);
		if (!ans[to[i]]) ans[to[i]]=x;
		else if (!ans[x]) ans[x]=to[i];
	}
	return ;
}
int main() 
{
	n=read();m=read();
	for (int i=1;i<=n;i++) fa[i]=i;
	for (int i=1;i<=m;i++)
	{
		int x=read(),y=read();
		int r1=find(x),r2=find(y);
		if (unionn(r1,r2)) add(x,y);
	}
	for (int i=1;i<=n;i++)
		if (!vis[find(i)])
			return puts("NIE"),0;
	for (int i=1;i<=n;i++)
	{
		int x=find(i);
		if (jud[x]) continue;
		dfs(x,0),jud[x]=1;
 	}
	puts("TAK");
	for (int i=1;i<=n;i++) 
		cout<<ans[i]<<endl;
	return 0;
}


猜你喜欢

转载自blog.csdn.net/acerandaker/article/details/81021128