欧拉图的判定和求法

 做一道Catenyms伤神无数,为避免此情况再次发生,在此将欧拉图的判定和求法加以总结

注:本篇文章系菜鸟总结,大神们请自行忽略。
欧拉图的判定:

1.首先,所有结点必须在同一个图中。——-》采用并查集判定

2.对于具有欧拉回路的图:所有结点的入度和出度都相等,奇数度的结点个数为0——–》统计判定

3.对于具有欧拉通路的图:图中一个结点的入度比出度大1,一个结点的入度比出度小1,其余结点入度和出度相同。奇数度结点的个数为2—–》统计判定

所有不满足以上条件的图都不是欧拉图。

欧拉图的求法:

1.Fleury算法:(下面这段话来自离散课本)

(1)任取v0∈V(G),令P0=v0.  

(2)设Pi=v0e1v1e2…eivi已经行遍,按下面方法来从E(G)-{e1,e2,…,ei}中选取ei+1:    

(a)ei+1与vi相关联;    

(b)除非无别的边可供行遍,否则ei+1不应该为Gi=G-{e1,e2,…,ei}中的桥。  

(3)当(2)不能再进行时,算法停止。

这个可能实现起来比较麻烦,因为还需要判断边是否是桥。

这个有兴趣的话可以去http://wenku.baidu.com/view/c32d8f49e45c3b3567ec8b40.html看看,要两个财富点。。穷人下不起

2.套圈法:(下面这段话来自黑书)

欧拉回路:标记1为待查找状态古城Euler(i)寻找开始于定点i并且结束与i的欧拉回路,具体步骤如下:

(1)寻找从i出发的环P1P2…Px(P1=Px=i)

(2)标记顶点P1→x为待查找状态。

(3)对所有处于待查找状态的结点Pj递归调用Euler(Pj)

将Pj找到的环Q1Q2…Qy插入到P1P2…Px中得到欧拉回路P1P2…PjQ2…QyPj+1…Px

如果是求欧拉通路,预处理时找到度数为奇数的两个结点x和y以及一条从x到y的边P1P2…Pk(x=P1;y=Pk),并初始化p[1]=k,p[i]=Pi(1<=i<=k)

这个算法的事件复杂度为O(m)

伪代码讲解:

Euler(int i,int id)

{

如果点i还有出路未使用

{

找到该出路的目标结点j,该出路的边的编号k

标记该出路已使用

Euler(j,k);

}

if (id!=-1) ans[top++]=该出路

}

以此图说明:

首先找到A的出路1,然后到达结点C

找到C的唯一可用出路2,到达A

找到A中可用出路3,到达B

找到B的唯一可用出路4,回到A。

回溯时会依次将欧拉路4321存在ans数组里,即得到答案。

 

3.dfs法,来自YY

 

44 bool dfs(int st,int cnt)

45 {

46 int i;

47 if(cnt==n)

48 return 1;

49 for(i=0;i&lt;n;i++)

50 {

51     if(edge[i].st&lt;st||used[i])

52                                 continue;

53          else if(edge[i].st&gt;st)

54                                  return false;

55     used[i]=true;

56     edge_order[cnt]=i;

57     if(dfs(edge[i].en,cnt+1))

58                               return 1;

59     used[i]=false;//回溯判断是否形成欧拉路径

60 }

?

这个很好理解吧,就是深度搜索,直到找到欧拉回路为止,算法复杂度比套圈什么的要高一些。推荐套圈。

 

 

你可能感兴趣的:(ACM,欧拉图)