離散實驗——歐拉圖的判定和應用


實驗六歐拉圖判定和應用

【實驗目的】掌握判斷歐拉圖的方法。

【實驗內容】編程隨機生成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;
}

 

過一學期了第一次寫離散作業


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM