并查集+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;
}