• 用并查集判断一个无向图中是否存在环


    并查集是一种树型的数据结构,用于处理一些不相交集合(Disjoint Sets)的合并及查询问题。常常在使用中以森林来表示。集就是让每个元素构成一个单元素的集合,也就是按一定顺序将属于同一组的元素所在的集合合并。

    • Find:确定元素属于哪一个子集。它可以被用来确定两个元素是否属于同一子集合。
    • Union:将两个子集合并成同一个集合。

    其实判断一个图是否存在环已经有相应的算法,此文用并查集来判断一个图是否有环。

    我们可以用一个一维数组parent[] 来记录子集合。

    看下面这个图:

    0

    |                   

    |    

    1——2

    对每一条边的两个顶点加入集合,发现两个相同的顶点在一个子集合中,就说明存在环。

    初始化:parent[n] 的每个元素都为-1,共有n个子集合,表示集合只有当前顶点一个元素

    0    1     2

    -1   -1   -1

    然后逐个处理每条边。

    边0-1:我们找到两个子集合 0 和1,因为他们在不同的子集合,现在需要合并他们(Union). 把其中一个子集合作为对方的父集合.

    0    1   2     <----- 1 成为 0 的 父集合 (1 现在代表集合 {0, 1})

    1    -1  -1

    边0-2:1属于属于子集合1,2属于子集合2,因此合并他们。

    0   1    2     <----- 2 作为 1的父集合 (2 现在代表集合 {0, 1, 2})

    1   2   -1

     边0-2: 0是在子集和2和2也是在子集合2, 因为 0->1->2 // 1 是0 父集合 并且  2 是1的父集合 。因此,找到了环

    // 用并查集判断是否存在环
    002
    #include <stdio.h>
    003
    #include <stdlib.h>
    004
    #include <string.h>
    005
     
    006
    // 图中的边
    007
    struct Edge
    008
    {
    009
        int src, dest;
    010
    };
    011
     
    012
    // 图结构体
    013
    struct Graph
    014
    {
    015
        // V-> 顶点个数, E-> 边的个数
    016
        int V, E;
    017
     
    018
        // 每个图就是 边的集合
    019
        struct Edge* edge;
    020
    };
    021
     
    022
    // 创建一个图
    023
    struct Graph* createGraph(int V, int E)
    024
    {
    025
        struct Graph* graph = (struct Graph*) malloc( sizeof(struct Graph) );
    026
        graph->V = V;
    027
        graph->E = E;
    028
     
    029
        graph->edge = (struct Edge*) malloc( graph->E * sizeof( struct Edge ) );
    030
     
    031
        return graph;
    032
    }
    033
     
    034
    // 查找元素i 所在的集合( 根 )
    035
    int find(int parent[], int i)
    036
    {
    037
        if (parent[i] == -1)
    038
            return i;
    039
        return find(parent, parent[i]);
    040
    }
    041
     
    042
    // 合并两个集合
    043
    void Union(int parent[], int x, int y)
    044
    {
    045
        int xset = find(parent, x);
    046
        int yset = find(parent, y);
    047
        parent[xset] = yset;
    048
    }
    049
     
    050
    // 检测环
    051
    int isCycle( struct Graph* graph )
    052
    {
    053
        int *parent = (int*) malloc( graph->V * sizeof(int) );
    054
     
    055
        // 初始化所有集合
    056
        memset(parent, -1, sizeof(int) * graph->V);
    057
     
    058
        // 遍历所有边
    059
        for(int i = 0; i < graph->E; ++i)
    060
        {
    061
            int x = find(parent, graph->edge[i].src);
    062
            int y = find(parent, graph->edge[i].dest);
    063
     
    064
            if (x == y) //如果在一个集合,就找到了环
    065
                return 1;
    066
     
    067
            Union(parent, x, y);
    068
        }
    069
        return 0;
    070
    }
    071
     
    072
    // 测试
    073
    int main()
    074
    {
    075
        /* 创建一些的图
    076
             0
    077
            |  
    078
            |    
    079
            1-----2 */
    080
        struct Graph* graph = createGraph(3, 3);
    081
     
    082
        // 添加边 0-1
    083
        graph->edge[0].src = 0;
    084
        graph->edge[0].dest = 1;
    085
     
    086
        // 添加边 1-2
    087
        graph->edge[1].src = 1;
    088
        graph->edge[1].dest = 2;
    089
     
    090
        // 添加边 0-2
    091
        graph->edge[2].src = 0;
    092
        graph->edge[2].dest = 2;
    093
     
    094
        if (isCycle(graph))
    095
            printf( "Graph contains cycle" );
    096
        else
    097
            printf( "Graph doesn't contain cycle" );
    098
     
    099
        return 0;
    100
    }
    View Code
  • 相关阅读:
    第三个实验代码
    20165104孟凡斌-第五周作业
    20165104孟凡斌-第四周作业
    20165104孟凡斌-第二次java考试课下作业
    20165104孟凡斌-第三周作业
    20165104孟凡斌-第二次JAVA作业
    20165104孟凡斌-第一次Java考试课下作业
    2018-2019-1 《信息安全系统设计基础》 20165235 实验五 通信协议设计
    2018-2019-1 20165235 实验四 外设驱动程序设计
    20165235 实现pwd功能
  • 原文地址:https://www.cnblogs.com/acm-jing/p/4655513.html
Copyright © 2020-2023  润新知