离散实验——欧拉图的判定和应用

时间:2024-01-30 20:42:00

实验六欧拉图判定和应用

【实验目的】掌握判断欧拉图的方法。

【实验内容】编程随机生成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;
}

 

过一学期了第一次写离散作业