P8655 [蓝桥杯 2017 国 B] 发现环 题解
small_lemon_qwq · · 题解
这道题我第一眼是觉得用Tarjan算法对原图构建一颗dfs树,如果某个顶点可以通过返祖边回到祖先,那答案就是祖先不经过返祖边到达这个顶点经过的所有点。
我们用样例举个例子。
先构建dfs树:
我们发现存在一条非树边 1 2 3 5。
code:
#include<bits/stdc++.h>
using namespace std;
#define int long long
int n,tim,dfn[200005],low[200005];
int ans,f[100005];
vector<int>g[200005];
void tarjan(int x){
dfn[x]=low[x]=++tim;
for(int&i:g[x]){
if(f[x]==i){//避免程序将(A->B)和(B->A)中的一个判为返祖边
continue;
}
if(!dfn[i]){
f[i]=x;
tarjan(i);
//此处不用取min
}else{
low[x]=min(low[x],dfn[i]);
}
}
if(low[x]<dfn[x]){//是返祖边
int y=x;
vector<int>ans;
while(dfn[y]!=low[x]){
ans.push_back(y);
y=f[y];
}
ans.push_back(y);
sort(ans.begin(),ans.end());//记得要排序
for(auto&x:ans){
cout<<x<<" ";
}
exit(0);//退出程序
}
}
signed main(){
cin>>n;
for(int i=1;i<=n;i++){
int u,v;
cin>>u>>v;
g[u].push_back(v);
g[v].push_back(u);//注意是无向图
}
tarjan(1);//其实从任意一个开始都可以,可以根据自己的喜好来
return 0;
}