一,定理及推论
1,无向图存在欧拉通路的充要条件,为连通图,仅存在两个奇度节点,或无奇度结点
2,无向图存在欧拉回路的条件,为连通图,不存在奇度点
3,有向图存在欧拉通路的条件,连通,所有点的出度等于入度,或仅存在两个顶点出度不等于入度,出、入度之 差为1的为起点,出入度之差为-1的为终点
4,有向图存在欧拉回路的条件,连通,所有点的出度等于入度
二 、欧拉图的判定
题目链接:点击打开链接
无向图判断是否存在欧拉回路
1.是连通图 2.无奇数度的点
连通图的判断可以用并查集,判断有误奇数点只要用一个数组记录就可以
有向图判断是否存在欧拉回路
1.是连通图 2,所有点的出度等于入度
与无向图类似,区别在于用两个数组分别记录顶点的出度数和入度数
三、欧拉通路的判定
题意:
一幅无向图,每条边只能经过一次,需要几次才能经过所有的边
输入n,m,n个点,m条边接着m行数据每行表示起点和终点
思路:一副连通的图,有几对奇数点度,就要相应的次数遍历完
1.需要判断有几幅连通图,单源点应该排除,输入的时候
不输入
2.每一幅图判断几对奇数点,奇数点个数除 2 等于
需要遍历的次数
代码:
#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
int od[100005];//记录节点度数
int father[100005];//父节点
int rk[100005];//优化
int vis[100005];//记录父节点
int num[100005];//连通图奇数度节点个数
int find(int x)
{
if (x!=father[x])
return find(father[x]);
else
return x;
}
void hebing(int x,int y)
{
if (rk[x]>rk[y])
{
father[x]=y;
}
else
{
father[y]=x;
if (rk[x]==rk[y])
rk[x]++;
}
}
int main()
{
int n,m,sum;
int i,j,k,a,b;
while (~scanf ("%d %d",&n,&m))
{
sum=0;
memset(od,0,sizeof(od));
memset(vis1,0,sizeof(vis1));
for (i=0; i<=n; i++)
{
father[i]=i;
rk[i]=0;
vis[i]=0;
num[i]=0;
}
for (i=0; i<m; i++)
{
scanf ("%d%d",&a,&b);
if (a==b)//排除单源点
continue;
od[a]++; od[b]++;
if (find(a)!=find(b))
hebing(find(a),find(b));//生成连通图
}
for (i=1; i<=n; i++)
{
if (od[i]!=0)//改点在图内
{
if (od[i]%2!=0)
{
num[find(i)]++;//记录每个连通图所有奇数度的个数
vis[find(i)]=1;//该连通图已经被找过
}
}
}
for (i=1; i<=n; i++)
{
if (od[i]!=0)
{
if (!vis[find(i)])//是连通图但是不存在奇数度点
{
num[find(i)]++;
vis[find(i)]=2;
}
else
if (vis[find(i)]==1)//存在奇数度的连通图除 2
{
num[find(i)]/=2;
vis[find(i)]=2;
}
}
}
for (i=1; i<=n; i++)
{
sum+=num[i];
}
printf("%d\n",sum);
}
}
练习