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

5 篇文章 0 订阅
4 篇文章 0 订阅

不知道前向星的看这里(转):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;
} 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值