并查集与欧拉回路

因为“并查集详解”这篇文章写得相当精彩,本文有许多从中借鉴。链接:http://blog.csdn.net/dellaserss/article/details/7724401

1.并查集

并查集采用树形数据结构,用于解决不相交集合的合并和查询问题。
我们来看一个例子:假设存在若干个城镇,其中一些城镇有道路直接相连,现在我们可以提出这么一些问题:
1)给你两个点(城镇可以看成点)让你判断这两个点是否连通。
2)请求出这若干个城镇组成的图中存在几个连通分支。
3)如果要把这整个图构建成一个连通图,要至少添加几条边。
如果你觉得对以上问题感到不知从何下手,那么学完并查集就可以轻松解决。
基本思路 :对于属于同一个集合的元素,选取一个元素作为根,其余相连的元素组成父子关系,形成树状结构。数组元素表示parent[x]=y表示元素x的父亲是元素y,对于根元素r,设置parent[r]=r。这样组建完,判断两个元素是否属于同一个集合就很简单了,只需要判断它们所属集合的根元素是否一致即可。
路径压缩 :如果查找一个元素x的父亲,parent[x]=y,y!=r,r是根元素,那么设置parent[x]=r,以及x原来的父级以上的元素的父亲都设置为r,这样以后再查x或其原来的父及以上元素的根元素的时候就不用逐级往上查,直接得到根元素,效率高。
查找元素所属集合的根元素的算法:
int find(int x){
    int cur=x;
    while(cur!=parent[cur]){
        cur=parent[cur]
    }
    int i=x,j;
    while(parent[i]!=cur){
        j=parent[i];
        parent[i]=cur;
        i=j;
    }
    return cur;
}
合并两个集合的算法:
void join(int x,int y){
    int r1=find(x),r2=find(y);
    if(r1!=r2){
        parent[r1]=r2;
    }
}

2.欧拉回路

欧拉回路是指在一个图中存在一个回路满足从一个点出发,不重复的走完图中的所有边,最后还是回到这个点。
欧拉回路实际上是欧拉路径的特例,欧拉路径是指在一个图中存在一个路径满足从一个点出发,不重复的走完图中的所有边,到达另一个点。欧拉回路是欧拉路径的出发点和终结点是同一个点的时候的情况。
判断是否存在欧拉路径的思路:
1)使用并查集判断所有点是否构成一个图
2)判断点的度,如果是有向图,只有一个点的出度比入度大1,且只有一个点的入度比出度大1,其余所有点的出度与入度都相等;如果是无向图,那么只有两个点的度是奇数,其他点的度都是偶数。
对于欧拉回路,只在2)中有所差异,对于有向图,所有点的入度与出度相等;对于无向图,所有点的度都是偶数。

有不少考查这方面的OJ题目,如华为OJ的“笔画”,POJ 1386等。

你可能感兴趣的:(数据结构)