Euler(歐拉通路)

記性不好 寫上來當做mark= =。。。

Time Limit: 1000 MS Memory Limit: 256 M

給出一幅n個點,m條邊的圖,分別判斷該圖是無向圖和有向圖條件下,是否存在歐拉通路。

輸入

輸入包含多組數據。第一行爲一個整數T(1 ≤ T ≤ 100),代表數據組數,對於每組數據: 第一行是兩個整數n和m( 1 ≤ n ≤ 500, 0 ≤ m ≤ n(n − 1)/2 ),分別代表圖上點的個數和邊的個數。
然後是m行,每行兩個整數ui和vi ( 1 ≤ ui, vi ≤ n, ui ≠ vi ),代表圖上的一條邊所連接的兩個點。輸入保證沒有重邊。

輸出

首先判斷:如果這幅圖是無向圖,是否存在歐拉通路;
其次判斷:如果這幅圖是有向圖,是否存在歐拉通路。
對於每個判斷,如果存在,輸出”Yes”,否則輸出”No”(不包括引號)。兩個判斷間用空格隔開。

樣例輸入

3

2 1
1 2

4 3
1 2
1 3
1 4

4 4
1 2
1 3
1 4
2 3

樣例輸出

Yes Yes
No No
Yes No

Hint

歐拉通路、歐拉回路、歐拉圖
無向圖:
1) 設 G 是連通無向圖,則稱經過 G 的每條邊一次並且僅一次的路徑爲歐拉通路;
2) 如果歐拉通路是迴路 (起點和終點是同一個頂點), 則稱此迴路爲歐拉回路 (Euler circuit);
3) 具有歐拉回路的無向圖 G 稱爲歐拉圖(Euler graph)。
有向圖:
1) 設 D 是有向圖, D 的基圖連通,則稱經過 D 的每條邊一次並且僅一次的有向路徑爲有向歐拉通路;
2) 如果有向歐拉通路是有向迴路,則稱此有向迴路爲有向歐拉回路(directed Euler circuit);
3) 具有有向歐拉回路的有向圖 D 稱爲有向歐拉圖(directed Euler graph)。

Extend

歐拉回路打印路徑算法:Fleury(佛羅萊)算法

Author

GooZy

題意:
分別判斷一個圖有向或無向時,是否有歐拉通路。

思路:
離散課講過七橋問題,如果一個無向圖要有歐拉通路的充分必要條件:奇數度的點只有兩個(因爲進入一個點,如果不是最後一個點或者第一個點的話 你肯定需要出來,所以其他點必須是偶數度點。)或者奇數度點爲0。
有向圖有歐拉回路的充要條件:
除兩個頂點外,其餘頂點的入度均等於出度,這兩個特殊的頂點中,一個頂點的入度比出度大1,另一個頂點的入度比出度小1。或者所有點的入度==出度。

wa點:
這個圖可能是不連通的。。
一個並查集可以搞定。。

#include <cstdio>
#include <iostream>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
#include <map>
using namespace std;
const int maxn=505;
int T,n,m,u,v;
int d[maxn],rd[maxn],cd[maxn];
int fa[maxn];
vector <int> G[maxn];
int find(int x){
    int r=x;
    while(fa[r]!=r){
        r=fa[r];
    }
    int i=x,t;
    while(fa[i]!=r){
        t=fa[i];
        fa[i]=r;
        i=t;
    }
    return r;
}
int main(){
    freopen("in.txt","r",stdin);
    scanf("%d",&T); 
    while(T--){
        scanf("%d%d",&n,&m);
        memset(d,0,sizeof d);
        memset(rd,0,sizeof rd);
        memset(cd,0,sizeof cd);
        int flag=0;
        for(int i=1;i<=n;i++) fa[i]=i;
        for(int i=1;i<=m;i++){
            scanf("%d %d",&u,&v);
            d[u]++;
            d[v]++;
            rd[v]++;
            cd[u]++;
            int x=find(u);
            int y=find(v);
            fa[x]=y;
        }
        for(int i=2;i<=n;i++)
            {
                int r=find(i);
                if(r!=find(1)){
                    flag=1;
                    break;
                }
            }
        if(flag==1){
            printf("No No\n");
            continue;
        }
        int ans=0;
        for(int i=1;i<=n;i++)
            if(d[i] & 1) ans++;
        if(ans==0 || ans==2) printf("Yes ");
        else printf("No ");
        vector <int> dd;
        dd.clear();
        for(int i=1;i<=n;i++)
            if(rd[i]!=cd[i]){
                dd.push_back(i);
            }
        //cout<<dd.size()<<endl;

        if(dd.size()==0) {
            printf("Yes\n");
            continue;
        }
        if(dd.size()!=2) printf("No\n");
        else {
            u=dd[0];
            v=dd[1];
            int x1=rd[u]-cd[u];
            int x2=rd[v]-cd[v];
            if((x1==-1 && x2==1) || (x1==1 && x2==-1)) printf("Yes\n");
            else printf("No\n");
        }
    }
} 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章