题记
主要考察并查集。如果直接dfs然后用vector保存路径,100000的数据量有点可怕。首先对于每一个链子,看两端的端点的根结点是否一样,如果一样,他们之间还又增添了新的通路,他们之间的通路就不唯一了(一条是直接相连,其他的是通过共同的根结点)那么就必然有环的存在。找到了出现环的位置,我们就得到了两个结点,大家可以dfs也可以像我下面写的那样,先保存一下其中一个结点直到根结点的路径,然后用同样的方法走一遍另一个结点通往根结点的路径,走的过程中发现的第一个存在于以求得的那条路径中的结点就是环的终点。再把这两条路径用vector保存一下,然后sort就可以了。
代码如下
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
const int Maxn=1e5+10;
int UFS[Maxn];
vector<int> path1,path2;//记录从某一个相交点出发到根节点的路径
vector<int> ans;
int findRoot(int x){
while(UFS[x]!=x){
x=UFS[x];
}
return x;
}
int main()
{
int n,a,b,conj;
int loop1,loop2;
cin>>n;
for(int i=1;i<=n;i++)//初始化
UFS[i]=i;
for(int i=0;i<n;i++){
cin>>a>>b;
if(b<a){
int tmp=b;
b=a;
a=tmp;
}
if(findRoot(a)==findRoot(b)){
loop1=a;
loop2=b;
}
else{
UFS[b]=a;
}
}
int temp=loop2;
while(true){
if(temp==findRoot(temp)){
path1.push_back(temp);
temp=UFS[temp];
break;
}
else{
path1.push_back(temp);
temp=UFS[temp];
}
}
temp=loop1;
while(true){
if(find(path1.begin(),path1.end(),temp)==path1.end())
temp=UFS[temp];
else{
conj=temp;
break;
}
}
while(loop1!=conj){
ans.push_back(loop1);
loop1=UFS[loop1];
}
while(loop2!=conj){
ans.push_back(loop2);
loop2=UFS[loop2];
}
ans.push_back(conj);
sort(ans.begin(),ans.end());
for(int i=0;i<ans.size();i++){
cout<<ans[i];
if(i!=ans.size()-1)
cout<<" ";
}
return 0;
}