歐拉回路
1.題目描述:
歐拉回路是指不令筆離開紙面,可畫過圖中每條邊僅一次,且可以回到起點的一條迴路。現給定一個圖,問是否存在歐拉回路?
輸入描述:
測試輸入包含若干測試用例。每個測試用例的第1行給出兩個正整數,分別是節點數N ( 1 < N < 1000 )和邊數M;隨後的M行對應M條邊,每行給出一對正整數,分別是該條邊直接連通的兩個節點的編號(節點從1到N編號)。當N爲0時輸入結束。
輸出描述:
每個測試用例的輸出佔一行,若歐拉回路存在則輸出1,否則輸出0。
示例1
輸入
複製
3 3
1 2
1 3
2 3
3 2
1 2
2 3
0
輸出
複製
1
0
2.基本思路
歐拉回路定義:於無向圖而言,存在歐拉回路的圖指的是能通過圖中所有的邊有且僅有一次,然後可以回到原點的圖。
需要滿足兩個要求:
①圖是連通圖(除了孤立頂點以外)→採用並查集進行判斷
②圖中所有頂點的度數(入度+出度)均爲偶數→採用inDegree數組進行標記
注意點:孤立點指的是隻存在單點回路或不存在任何與其相連的邊的頂點。
以下圖爲例Figure.1中的結點2、4均爲孤立頂點,Figure.2爲非連通圖。
需要注意一下用例:
用例:
7 8
2 6
5 4
6 6
2 1
2 2
5 6
1 4
5 5
對應輸出應該爲:
1
該例中很明顯結點3,7是孤立的結點,但歐拉圖只要求通過所有的邊,然後能回到原點即可,因此對於孤立的點可以無需考慮,這裏採用set存儲非孤立的結點的編號。後續統計度數的奇偶性以及連通分量的個數時可以忽略這些孤立的頂點不管。
3.代碼實現
#include <iostream>
#include <set>
#define N 1001
using namespace std;
int Tree[N];
int inDegree[N];
set<int> Mapping;
int findRoot(int x){
if(Tree[x]==-1)return x;
else{
Tree[x]=findRoot(Tree[x]);
return Tree[x];
}
}
int main()
{
int n,m;
int a,b;
while(~scanf("%d",&n)){
if(n==0)break;
scanf("%d",&m);
for(int i=1;i<=n;i++){
Tree[i]=-1;
inDegree[i]=0;
}
for(int i=1;i<=m;i++){
scanf("%d%d",&a,&b);
if(a==b)continue;//單點回路忽略不計
Mapping.insert(a);
Mapping.insert(b);
inDegree[a]++;
inDegree[b]++;
a = findRoot(a);
b = findRoot(b);
if(a!=b)Tree[a]=b;
}
int cnt=0;//統計連通分量的個數
for(auto it=Mapping.begin();it!=Mapping.end();it++){
if(Tree[*it]==-1)cnt++;
}
if(cnt!=1){
printf("0\n");
}
else{
int cnt1=0;//統計度數爲奇數的結點個數
for(auto it=Mapping.begin();it!=Mapping.end();it++){
if(inDegree[*it]&1==1){
cnt1++;
}
}
if(cnt1==0){
printf("1\n");
}
else{
printf("0\n");
}
}
}
return 0;
}
/*
3 3
1 2
1 3
2 3
3 2
1 2
2 3
0
*/