前言
找有向图中的环很简单,因为tarjan是一个现成的模板,而无向图找环就有点复杂了,比较考察dfs的能力。
如何找无向图中的环呢?
首先,我们把一个边的两边加入并查集,当我们新加入的边已经在并查集内时,这个边就构成了环。这个边的两端可以看作环的起点和终点。
然后我们从起点开始dfs到终点,这中间的路径就是环上的点。
所以我们从起点开始,如果遇到了没访问过的点,我们就继续从该点开始遍历。如果走到死路,我们就要回溯了。回溯很重要,如果不回溯的话,那么走到死路之后这个算法就不能继续下去了。
代码如下:
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5+7;
vector<int> G[maxn];
int n,s,t;
int p[maxn];
int ans[maxn];
int vis[maxn];
void init()
{
for(int i=0;i<maxn;i++) p[i] = i;
}
int find(int x)
{
if(x==p[x]) return x;
return p[x] = find(p[x]);
}
void unite(int x,int y)
{
x = find(x);
y = find(y);
if(x==y) return;
p[x] = y;
}
bool same(int x,int y)
{
return find(x)==find(y);
}
void dfs(int now,int stp)
{
ans[stp] = now;
if(now==t)
{
sort(ans,ans+stp+1);
for(int i=0;i<=stp;i++) printf("%d ",ans[i]);
return;
}
vis[now] = 1;
for(int i=0;i<G[now].size();i++)
{
int v = G[now][i];
if(!vis[v])
{
vis[v] = 1;
dfs(v,stp+1);
vis[v] = 0;
}
}
}
int main()
{
init();
scanf("%d",&n);
for(int i=0;i<n;i++)
{
int a,b;
scanf("%d%d",&a,&b);
if(same(a,b))
{
s = a;
t = b;
continue;
}
unite(a,b);
G[a].push_back(b);
G[b].push_back(a);
}
dfs(s,0);
return 0;
}