欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

链式前向星找环路径 dfs+并查集 裸题

程序员文章站 2022-05-13 17:14:32
...

不知道前向星的看这里(转):https://blog.csdn.net/Courage_kn/article/details/77015183 

前向星dfs bfs 看这里(转):https://blog.csdn.net/m0_37830950/article/details/77996083

最后说明的:1:无向图(双向边)一定要开2倍空间,一定要开2倍,开2倍,不开提交会报运行错

                      2:我在保存边只走一次或者点只走一次的时候喜欢多加个录入时边的编号(index),第一条录入的边是1,第二条是2,这样查重脑子不会乱,一般的dfs可以直接像上面转载的!vis[e[i].to])。


题目来源(蓝桥历届试题 发现环

题目描述:多了一个边成环,找环上所有点,由小到大输出。

样例输入

5
1 2
3 1
2 4
2 5
5 3

样例输出

1 2 3 5

#include<bits/stdc++.h>
using namespace std;
const int maxn=100010;
struct EG{
    int to,next,index;
}e[maxn*2];
int pre[maxn],head[maxn],vis[maxn];
int cnt=0,qs,zd,n;
void init(){
    memset(head,-1,sizeof head);
    for(int i=1;i<=n;i++)
    pre[i]=i;
}
int find(int x){
    return x==pre[x]?x:pre[x]=find(pre[x]);
}
void un(int a,int b){
    int fa=find(a);
    int fb=find(b);
    if(fa==fb) {qs=a,zd=b;return;}
    else pre[fa] = fb;
}
void add(int x,int y,int i){ //加边和边的编号 
    e[++cnt].to=y;
    e[cnt].next=head[x];
    e[cnt].index=i;
    head[x]=cnt;
}
int loop=0,num[maxn]; 
void dfs(int x){
    if(loop==1) return;//剪枝,不加也能ac 
    if(x==zd){
    loop=1;   
    for(int i=1;i<=n;i++)
    if(num[i]==1) printf("%d%c",i,i==n?'\n':' ');
    return;
    }
    for(int i=head[x];~i;i=e[i].next){
        if(vis[e[i].index]==1) continue;
            vis[e[i].index]=1;//每个边只走一次 
            num[e[i].to]=1;
            
            dfs(e[i].to);
            
            vis[e[i].index]=0;
            num[e[i].to]=0;    
    }
}
int main(){
    scanf("%d",&n);
    init();
    int f=1;
    for(int i=1;i<=n;i++){
        int a,b;
		scanf("%d %d",&a,&b);
        if(find(a)!=find(b)){
        add(a,b,i);
        add(b,a,i);
        un(a,b);        
        }
        else{    
                qs=a,zd=b;
            	num[qs]=num[zd]=1;
               dfs(qs);//剪枝,不加的话就是把dfs放在循环外,也能ac。 
		       break;
           }               
}
    return 0;
} 

 

相关标签: 找环