定义:对于无孤立节点图G,若存在一条路经过图中每一条边且只经过一次,该条路称为欧拉路。若该路径为一个圈,则称为欧拉回路。
欧拉路的判定:
(1)一个无向图存在欧拉路径,当且仅当该图是连通的,且只存在零个或两个奇数度的顶点。
(2)一个有向图存在欧拉路径,当且仅当该图是连通的,且该图的所有顶点度数为0,或仅存在一个度数为1的顶点和一个度数为-1的顶点,其余点的度数均为0。
欧拉回路的判定:
(1)一个无向图存在欧拉回路,当且仅当该图是连通的,且不存在奇数度的顶点。
(2)一个有向图存在欧拉回路,当且仅当该图是连通的,且所有顶点的入度等于出度。
对于度数的奇偶性,我们可以用非(!)运算来表示:1表示奇度,0表示偶度。接下来就是判断图的连通性了:搜索或者并查集都行,下面分别给出代码。
无向图的欧拉路径(题目链接:http://hihocoder.com/problemset/problem/1176 )
并查集实现代码如下:
#include <cstdio> #include <cstring> #include <iostream> using namespace std; const int maxn=10005; int ind[maxn]; int par[maxn],ran[maxn]; void init(int n) { for(int i=1;i<=n;i++) { par[i]=i; ran[i]=1; } } int Find(int x) { if(par[x]!=x) return par[x]=Find(par[x]); return x; } void Union(int x,int y) { x=Find(x); y=Find(y); if(x==y) return ; if(ran[x]>ran[y]) { par[y]=x; ran[x]+=ran[y]; } else { par[x]=y; ran[y]+=ran[x]; } } int main() { int n,m; while(scanf("%d%d",&n,&m)!=-1) { init(n); int u,v; memset(ind,0,sizeof(ind)); for(int i=0;i<m;i++) { scanf("%d%d",&u,&v); Union(u,v); ind[u]=!ind[u]; //纪录每个顶点度数的奇偶性:1为奇度,0为偶度 ind[v]=!ind[v]; } int sum_par=0,sum_ind=0; for(int i=1;i<=n;i++) { if(par[i]==i) sum_par++; if(ind[i]) sum_ind++; } if(sum_par>1) { puts("Part"); //不存在欧拉路 continue; } if(sum_ind==0||sum_ind==2) puts("Full"); //存在欧拉路 else puts("Part"); //不存在欧拉路 } return 0; }
DFS实现代码如下:
#include <iostream> #include <cstdio> #include <cstring> using namespace std; const int maxn=10005; typedef struct { int to,nex; }EDGE; EDGE edge[5*maxn]; int head[maxn],cnt; int ind[maxn]; bool vis[maxn]; void add(int u,int v) { edge[cnt].to=v; edge[cnt].nex=head[u]; head[u]=cnt++; } void dfs(int x) { vis[x]=true; for(int i=head[x];i!=-1;i=edge[i].nex) if(!vis[ edge[i].to ]) dfs(edge[i].to); } int main() { int n,m; while(scanf("%d%d",&n,&m)!=-1) { cnt=0; memset(head,-1,sizeof(head)); memset(vis,false,sizeof(vis)); memset(ind,0,sizeof(ind)); for(int i=0;i<m;i++) { int u,v; scanf("%d%d",&u,&v); add(u,v); ind[u]=!ind[u]; ind[v]=!ind[v]; } dfs(1); bool flag=false; for(int i=1;i<=n;i++) if(!vis[i]) flag=true; if(flag) { puts("Part"); //不存在欧拉路 continue; } int sum_ind=0; for(int i=1;i<=n;i++) if(ind[i]) sum_ind++; if(sum_ind==0||sum_ind==2) puts("Full"); else puts("Part"); } return 0; }
对于欧拉回路,大体上和欧拉路的求解方法一致,只是在判断度数的奇偶性上略有差异。