并查集判断是否有环

本文介绍了如何利用并查集判断无向图是否存在环路,通过将节点分到不同的根节点并检查连接节点的根是否相同来实现。同时,对于有向图,通过拓扑排序和visited数组记录节点状态来检测环路。在无环的情况下,进行并查集操作或拓扑排序后,系统会输出"无环",否则提示"有环"。
摘要由CSDN通过智能技术生成

对于无向图来说,用并查集的思路,将每个结点分到不同的根节点团伙中,判断两个团伙是否有相同的根结点,如果如果两个相连接的结点有共同的根,则说明有环。

#include<bits/stdc++.h>
using namespace std;
int fa[10005];//代表元素数组
int depth[10005];//深度数组
int n,m;//n为顶点数,m为边的条数
void init()//注意初始化
{
    for(int i=0;i<n;i++)
    {
        fa[i]=-1;
        depth[i]=0;
    }
}
int find_root(int x)
{
    int x_root=x;
    while(fa[x_root]!=-1)//只要还没找到头结点(根),那么就要一直往上找
    {
        x_root=fa[x_root];
    }
    return x_root;
}
int Union(int x,int y)
{
    int x_root=find_root(x);
    int y_root=find_root(y);
    if(x_root==y_root)//如果需要合并的两个元素本来就是一个集合的,那么就说明存在环
    {
        return 0;
    }else
    {
        if(depth[x_root]>depth[y_root])//左深右浅右插左
        {
            fa[y_root]=x_root;
        }else if(depth[x_root]<depth[y_root])//右深左浅左插右
        {
            fa[x_root]=y_root;
        }else
        {
            depth[y_root]++;//若两侧深度相同,那么我们固定x到y下面插,并且y的深度+1
            fa[x_root]=y_root;
        }
        return 1;
    }
}
int main()
{
    int edge[100005][2];
    cin>>n>>m;//读入顶点数和边的条数
    init();
    for(int i=0;i<m;i++)
    {
        cin>>edge[i][0]>>edge[i][1];//读入边
    }
    for(int i=0;i<m;i++)
    {
        int x=edge[i][0];
        int y=edge[i][1];
        if(Union(x,y)==0)
        {
            cout<<"有环"<<endl;
            return 0;
        }
    }
    cout<<"无环"<<endl;
    return 0;
}

 对于有向图来说,使用拓扑排序,visited数组记录该节点状态,1表示已经访问过,-1表示该节点所有邻接点都被访问了,0则表示未访问。

//color[i],为0表示未访问过,为1表示访问过,为-1表示该节点后边的节点都被访问过。
void DFS(int i){
		cout<<"正在访问结点"<<i;
		//结点i变为访问过的状态
		color[i] = 1;
		for(int j=1;j<=vNum;j++){
			//如果当前结点有指向的结点
			if(graph[i][j] != 0){	
				//并且已经被访问过
				if(color[j] == 1){
					isDAG = false;//有环
					break;
				}else if(color[j] == -1){
					//当前结点后边的结点都被访问过,直接跳至下一个结点
					continue;
				}else{
					DFS(j);//否则递归访问
				}
			}
		}
		//遍历过所有相连的结点后,把本节点标记为-1
		color[i] = -1;
	}

参考:并查集判断图中是否有环

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值