1348: [蓝桥杯2017决赛]发现环 (dfs+并查集)

在这里插入图片描述

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn=1e5+10;
int be,e; ///起点和终点
int n;
int ans[maxn];///结果数组,用于保存所有在环上的点
int fa[maxn];///并查集数组
int vis[maxn]; ///用于做标记,判断当前结点是否已经访问过
vector<int>v[maxn];///关系图,这里使用动态数组,为了节省不必要的空间
int xunzu(int x)///并查集核心代码(带路径压缩)
{
    if(x==fa[x])
    {
        return x;
    }
    else
    {
        return fa[x]=xunzu(fa[x]);
    }
}
//int xunzu(int x)
//{
//    return x == fa[x] ? x : fa[x] = xunzu(fa[x]);
//}
///x:当前结点 ----- len:结果数组长度
void dfs(int x,int len)
{
    ans[len]=x;  ///把当前在环上的结点存到结果数组中
    if(x==e)///如果当前结点已经访问到e,则此环已经访问完毕,直接输出结果即可
    {
        sort(ans,ans+len+1);///应题目要求,输出前先进行排序
        for(int i=0; i<=len; i++)
        {
            printf("%d",ans[i]);
            if(i!=len) printf(" ");
        }
        printf("\n");
        return ;
    }
    vis[x]=1; ///标记此结点已被访问过

    for(int i=0; i<v[x].size(); i++)///枚举x的关系表中所有连通的结点
    {
        if(vis[v[x][i]]==0)///如果v[x][i]这个结点没有被访问过,则递归进行访问
        {
            dfs(v[x][i],len+1);///结果数组长度要+1,否则会造成覆盖
        }
    }
    vis[x]=0;///回溯
}
int main()
{
    memset(vis,0,sizeof(vis));
    scanf("%d",&n);
    for(int i=1; i<=n; i++)
    {
        fa[i]=i;
    }

    for(int i=1; i<=n; i++)
    {
        int a,b;
        scanf("%d%d",&a,&b);
        int  aa=xunzu(a);
        int  bb=xunzu(b);
        if(aa!=bb)///如果当前两点没有连通,则把两点进行连通,并建立关系表
        {
            fa[aa]=bb;
            v[a].push_back(b);  ///当前x结点连通y结点
            v[b].push_back(a);///当前y结点连通x结点
        }
        else///如果当前两点已经连通则表明这两点必然在环上,记录两点,用于搜索
        {
            be=a;
            e=b;
        }
    }
//    printf("%d%d\n",be,e);
    dfs(be,0);///从be为起点搜索到e结束
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值