5-32 哥尼斯堡的「七橋問題」 (25分) 歐拉回路

題目描述:html

哥尼斯堡是位於普累格河上的一座城市,它包含兩個島嶼及鏈接它們的七座橋,以下圖所示。ios

能否走過這樣的七座橋,並且每橋只走過一次?瑞士數學家歐拉(Leonhard Euler,1707—1783)最終解決了這個問題,並由此創立了拓撲學。測試

這個問題現在能夠描述爲判斷歐拉回路是否存在的問題。歐拉回路是指不令筆離開紙面,可畫過圖中每條邊僅一次,且能夠回到起點的一條迴路。現給定一個無向圖,問是否存在歐拉回路?spa

輸入格式:

輸入第一行給出兩個正整數,分別是節點數NN (1\le N\le 10001N1000)和邊數MM;隨後的MM行對應MM條邊,每行給出一對正整數,分別是該條邊直接連通的兩個節點的編號(節點從1到NN編號)。code

輸出格式:

若歐拉回路存在則輸出1,不然輸出0。htm

輸入樣例1:

6 10
1 2
2 3
3 1
4 5
5 6
6 4
1 4
1 6
3 4
3 6

輸出樣例1:

1

輸入樣例2:

5 8
1 2
1 3
2 3
2 4
2 5
5 3
5 4
3 4

輸出樣例2:

0



第一次我蚍蜉撼樹採用了DFS深度搜索的方式解決,果真最後兩個測試點超時,下面 是我第一次嘗試的代碼:
#include<iostream>
#include<vector>
#define MAX 1000
using namespace std;
int g[MAX][MAX];
int from;
int been[MAX][MAX];
int cnt = 1;
void clear(int n)
{
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= n; j++)
            been[i][j] = 0;
}
bool DFS(int fr, int n, int m)
{
    //int been[MAX][MAX];
    for (int j = 1; j <= n; j++)
    {
        if (j != fr && been[fr][j] == 0 && g[fr][j] == 1)
        {
            //cout<<"fr :"<<fr<<" to "<<j<<endl;
            //cout<<"cnt is "<<cnt<<endl; 
            if (j == from)
            {
                if (cnt == m) return true;
                //cout<<"減啦"<<endl; 
                //cnt--;
                continue;
            }
            cnt++;
            been[fr][j] = been[j][fr] = 1;
            if (cnt == m) return true;
            return DFS(j, n, m);
        }
    }
    return false;
}
int main()
{
    int n, m, a, b;
    cin >> n >> m;
    int temp = m;
    while (temp--)
    {
        cin >> a >> b;
        g[a][b] = g[b][a] = 1;
    }
    for (int i = 1; i <= n; i++)
    {
        clear(n);
        cnt = 1;
        from = i;
        if (DFS(i, n, m)) {
            cout << 1;
            return 0;
        }
    }
    cout << 0;
    return 0;
}

 

在網上搜索得知這是有關歐拉回路的知識:blog

歐拉回路:圖G,若存在一條路,通過G中每條邊有且僅有一次,稱這條路爲歐拉路,若是存在一條迴路通過G每條邊有且僅有一次,ci

稱這條迴路爲歐拉回路。具備歐拉回路的圖成爲歐拉圖。數學

判斷歐拉路是否存在的方法string

有向圖:圖連通,有一個頂點出度大入度1,有一個頂點入度大出度1,其他都是出度=入度。

無向圖:圖連通,只有兩個頂點是奇數度,其他都是偶數度的。

判斷歐拉回路是否存在的方法

有向圖:圖連通,全部的頂點出度=入度。

無向圖:圖連通,全部頂點都是偶數度。

程序實現通常是以下過程:

1.利用並查集判斷圖是否連通,即判斷p[i] < 0的個數,若是大於1,說明不連通。

2.根據出度入度個數,判斷是否知足要求。

3.利用dfs輸出路徑。

正確代碼

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<sstream>
#include<algorithm>
#include<queue>
#include<vector>
#include<cmath>
#include<map>
#include<stack>
#include<set>
#include<fstream>
#include<memory>
#include<list>
#include<string>
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
#define MAXN  1003
#define LLL 1000000000
#define INF 1000000009
/*
DFS能搜到全部的點
*/
vector<int> E[MAXN];
int pre[MAXN],n,m;
int find(int x)
{
    if (pre[x] == -1)
        return x;
    else
        return pre[x] = find(pre[x]);
}
void mix(int x, int y)
{
    int fx = find(x), fy = find(y);
    if (fx != fy)
    {
        pre[fy] = fx;
    }
}
int main()
{
    memset(pre, -1, sizeof(pre));
    scanf("%d%d", &n, &m);
    int f, t;
    for (int i = 1; i <= n; i++)
        E[i].clear();
    while (m--)
    {
        scanf("%d%d", &f, &t);
        mix(f, t);
        E[f].push_back(t);
        E[t].push_back(f);
    }
    int cnt = 0, num = 0;
    for (int i = 1; i <= n; i++)
    {
        if (E[i].size() % 2)
            cnt++;
        if (find(i) == i)
            num++;
    }
    if (cnt == 0 && num == 1)
        printf("1\n");
    else
        printf("0\n");
    return 0;
}
相關文章
相關標籤/搜索