实验六欧拉图判定和应用
【实验目的】掌握判断欧拉图的方法。
【实验内容】编程随机生成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; }
过一学期了第一次写离散作业