离散实验——欧拉图的判定和应用
实验六欧拉图判定和应用
【实验目的】掌握判断欧拉图的方法。
【实验内容】编程随机生成n个结点的无向图(有向图)并能进行(半)欧拉图的判定,若是则给出所有欧拉路.
【要求】对给定n个结点,随机生成邻接矩阵以确定某无向简单图(有向图)并进行欧拉图和半欧拉图的判定,若符合则给出至少一条欧拉回路或欧拉路。
【实验原理和方法】
是根据随机生成的图求欧拉(回)路,先要随机生成一个邻接矩阵,然后判定是否是欧拉回路只要根据奇数度结点的个数。再用一个递归函数找出欧拉路。
(1)用关系矩阵R=表示图。
(2)对无向图而言,若所有结点的度都是偶数,则该图为欧拉图。
C语言算法:
flag=1;
for(i=1;i<=n && flag;i++)
{
sum=0;
for(j=1;j<=n;j++)
if(r[i][j]) sum++;
if(sum%2==0) flag=0;
}
如果 flag 该无向图是欧拉图
(3)对有向图而言,若所有结点的入度等于出度,则该图为欧拉图。
C语言算法:
flag=1;
for(i=1;i<=n && flag;i++)
{
sum1=0;
sum2=0;
for(j=1;j<=n;j++)
if(r[i][j]) sum1++;
for(j=1;j<=n;j++)
if(r[j][i]) sum2++;
if(sum1%2==0 || sum2%2==0) flag=0;
}
如果 flag 该有向图是欧拉图
(4)求出欧拉路的方法:欧拉路经过每条边一次且仅一次。可用回溯的方法求得所有欧拉路。
C语言算法:
intcount=0,cur=0,r[N][N]; // r[N][N]为图的邻接矩阵,cur为当前结点编号,count为欧拉路的数量。
int sequence[M];// sequence保留访问点的序列,M为图的边数
输入图信息;
void try1(int k) //k表示边的序号
{
int i,pre=cur; //j保留前一个点的位置,pre为前一结点的编号
for (i=0;i<N;i++)
if (r[cur][i]) //当前第cur点到第i点连通
{
//删除当前点与第i点的边,记下第k次到达点i,把第i个点设为当前点
r[cur][i]=0;cur=sequence[k]=i;
if (k<M) try1(k+1); //试下一个点
else prt1();//经过了所有边,打印一个解
//上面条件不满足,说明当前点的出度为0,回溯,试下一位置
r[pre][i]=1;cur=pre;
}
}
附上代码:
有向图:
- #include <stdio.h>
- #include <string.h>
- #include <stdlib.h>
- #include <time.h>
- int n,a[100][100],m=0,visit[100];
- int cur=0,s[100],vis[100][100];
- void try1(int k)//取欧拉路
- {
- int i;
- if(cur==m+1)
- {
- for(i=0;i<cur;i++)
- {
- if(i==0)
- printf("%d",s[i]+1);
- else
- printf("->%d",s[i]+1);
- }
- printf("\n");
- }
- else
- {
- for(i=0;i<n;i++)
- {
- if(a[k][i]&&!vis[k][i])
- {
- vis[k][i]=1;
- vis[i][k]=1;
- s[cur++]=i;
- try1(i);
- cur--;
- vis[k][i]=0;
- vis[i][k]=0;
- }
- }
- }
- }
- void dfs(int k)
- {
- int i;
- visit[k]=1;
- for(i=0;i<n;i++)
- {
- if(a[k][i]&&!visit[i])
- {
- dfs(i);
- }
- }
- }
- int fun()//判断连通性
- {
- int i;
- dfs(0);
- for(i=0;i<n;i++)
- {
- if(!visit[i])
- return 0;
- }
- return 1;
- }
- int main(void)
- {
- int i,j;
- memset(vis,0,sizeof(vis));
- memset(visit,0,sizeof(visit));
- srand(time(NULL));
- printf("请输入节点个数n:");
- scanf("%d",&n);
- for(i=0;i<n;i++)
- {
- for(j=0;j<n;j++)
- {
- if(i==j)
- a[i][j]=0;
- else if(i>j)
- a[i][j]=a[j][i];
- else
- a[i][j]=rand()%2;
- m+=a[i][j];
- }
- }
- m/=2;
- printf("邻接矩阵为:\n ");
- for(i=0;i<n;i++)
- {
- printf(" %d",i+1);
- }
- printf("\n");
- for(i=0;i<n;i++)
- {
- printf("%d",i+1);
- for(j=0;j<n;j++)
- printf(" %d",a[i][j]);
- printf("\n");
- }
- if(fun()==0)
- {
- printf("该图不是连通图!\n");
- return 0;
- }
- printf("该图是连通图!\n");
- int odd=0;
- for(i=0;i<n;i++)
- {
- int sum=0;
- for(j=0;j<n;j++)
- {
- if(a[i][j])
- sum++;
- }
- if(sum%2)
- odd++;
- }
- if(odd==0)
- {
- printf("该图没有奇数度节点,具有欧拉回路,是欧拉图。\n");
- printf("所有的欧拉路为:\n");
- for(i=0;i<n;i++)
- {
- s[cur++]=i;
- try1(i);
- cur--;
- }
- }
- else if(odd==2)
- {
- printf("该图有两个奇数度节点,具有欧拉路,是半欧拉图。\n");
- printf("所有的欧拉路为:\n");
- for(i=0;i<n;i++)
- {
- int sum=0;
- for(j=0;j<n;j++)
- sum+=a[i][j];
- if(sum%2)//起点或中点
- {
- s[cur++]=i;
- try1(i);
- cur--;
- }
- }
- }
- else
- {
- printf("不是欧拉图,也不是半欧拉图\n");
- }
- return 0;
- }
无向图:
- #include <stdio.h>
- #include <string.h>
- #include <stdlib.h>
- #include <time.h>
- int n,a[100][100],m=0,visit[100];
- int cur=0,s[100],vis[100][100];
- void try1(int k)//取欧拉路
- {
- int i;
- if(cur==m+1)
- {
- for(i=0;i<cur;i++)
- {
- if(i==0)
- printf("%d",s[i]+1);
- else
- printf("->%d",s[i]+1);
- }
- printf("\n");
- }
- else
- {
- for(i=0;i<n;i++)
- {
- if(a[k][i]&&!vis[k][i])
- {
- vis[k][i]=1;
- s[cur++]=i;
- try1(i);
- cur--;
- vis[k][i]=0;
- }
- }
- }
- }
- void dfs(int k)
- {
- int i;
- visit[k]=1;
- for(i=0;i<n;i++)
- {
- if(a[k][i]&&!visit[i])
- {
- dfs(i);
- }
- }
- }
- int fun()//判断连通性
- {
- int i,j;
- for(i=0;i<n;i++)
- {
- memset(visit,0,sizeof(visit));
- dfs(i);
- for(j=0;j<n;j++)
- {
- if(!visit[j])
- break;
- }
- if(j==n)
- return 1;
- }
- return 0;
- }
- int main(void)
- {
- int i,j;
- memset(vis,0,sizeof(vis));
- srand(time(NULL));
- printf("请输入节点个数n:");
- scanf("%d",&n);
- for(i=0;i<n;i++)
- {
- for(j=0;j<n;j++)
- {
- a[i][j]=rand()%2;
- m+=a[i][j];
- }
- }
- printf("邻接矩阵为:\n ");
- for(i=0;i<n;i++)
- {
- printf(" %d",i+1);
- }
- printf("\n");
- for(i=0;i<n;i++)
- {
- printf("%d",i+1);
- for(j=0;j<n;j++)
- printf(" %d",a[i][j]);
- printf("\n");
- }
- if(fun()==0)
- {
- printf("该图不是连通图!\n");
- return 0;
- }
- printf("该图是连通图!\n");
- int odd=0,begin=-1,end=-1;
- for(i=0;i<n;i++)
- {
- int sum1=0,sum2=0;
- for(j=0;j<n;j++)
- {
- sum1+=a[i][j];
- sum2+=a[j][i];
- }
- if(sum1!=sum2)
- {
- odd++;
- if(sum1-sum2==1)
- begin=i;
- if(sum2-sum1==1)
- end=i;
- }
- }
- if(odd==0)
- {
- printf("该图所有点出度等于入度,具有欧拉回路,是欧拉图。\n");
- printf("所有的欧拉路为:\n");
- for(i=0;i<n;i++)
- {
- s[cur++]=i;
- try1(i);
- cur--;
- }
- }
- else if(odd==2&&begin!=-1&&end!=-1)
- {
- printf("该图有两个奇数度节点,具有欧拉路,是半欧拉图。\n");
- printf("所有的欧拉路为:\n");
- s[cur++]=begin;
- try1(begin);
- }
- else
- {
- printf("不是欧拉图,也不是半欧拉图\n");
- }
- return 0;
- }
过一学期了第一次写离散作业