ACM演算法之 歐拉回路
阿新 • • 發佈:2019-01-31
- 題目描述:
- 歐拉回路是指不令筆離開紙面,可畫過圖中每條邊僅一次,且可以回到起點的一條迴路。現給定一個圖,問是否存在歐拉回路?
- 輸入:
- 測試輸入包含若干測試用例。每個測試用例的第1行給出兩個正整數,分別是節點數N ( 1 < N < 1000 )和邊數M;隨後的M行對應M條邊,每行給出一對正整數,分別是該條邊直接連通的兩個節點的編號(節點從1到N編號)。當N為0時輸入結束。
- 輸出:
- 每個測試用例的輸出佔一行,若歐拉回路存在則輸出1,否則輸出0。
- 樣例輸入:
-
3 3 1 2 1 3 2 3 3 2 1 2 2 3 0
- 樣例輸出:
-
1 0
什麼是歐拉回路?
這個我起初以為很簡單,就是一個環而已,所以每個頂點只要出現偶數次(至少是2次,不能是0次),就說明有環。
#include <stdio.h> #include <string.h> int du[1000]; int main() { int n, m; int u, v; int i; while(scanf("%d", &n) && n != 0) { memset(du, 0, sizeof(du)); scanf("%d", &m); while(m--) { scanf("%d %d", &u, &v); du[u]++; du[v]++; } int flag = 1; for(i = 1; i <= n; i++) { if(du[i]&1){ flag = 0; break; } } printf("%d\n",flag); } return 0; }
/**************************************************************
Problem:
1027
User:
從此醉
Language:
C
Result:
Accepted
Time:60
ms
Memory:908
kb
****************************************************************/
太簡單了吧? 在九度OJ是可以過的,只能說明這個OJ太弱了。
換到HDU就不行了。因為沒有考慮到 獨立環 這種情況。題目要求是:每天邊都要遍歷,而且只能有一次。
所以,符合下面兩點就行了:
1、可以用並查集,來檢測是不是所有點都在一個集合裡。
2、每個點 上的邊是偶數。因為,如果 (1)這個點是起點,肯定有一條邊出,一條邊進,2條邊。如果(2)這個點不是起點,肯定是有進必有出,即偶數!
#include <stdio.h>
int arr[1000];
int father[1000];
int rand_deep[1000];
int findSet(int x){
int px = x,i;
while(px != father[px])
px = father[px];
//路徑壓縮,加快查詢速度
while(x != px){
i = father[x];
father[x] = px;
x = i;
}
return px;
}
void unionSet(int x,int y){
x = findSet(x);
y = findSet(y);
if(rand_deep[x] > rand_deep[y])
father[y] = x;
else{
father[x] = y;
if(rand_deep[x]==rand_deep[y])rand_deep[y]++;
}
}
int main() {
int N,M;
while( scanf("%d",&N) != EOF && N){
scanf("%d",&M);
int i;
int flag = 1;
for(i=1; i<=N; i++){
father[i] = i;
rand_deep[i] = 0;
arr[i] = 0;
}
for(i=0; i<M; i++){
int x,y;
scanf("%d %d",&x, &y);
arr[x] ++;
arr[y] ++;
unionSet(x , y);
}
int father;
for(i=1; i<=N; i++){
if(i==1)
father = findSet(1);
else{
if(father!=findSet(i)){
flag = 0;
break;
}
}
if(arr[i] == 0 || arr[i]%2 != 0){
flag = 0;
break;
}
}
printf("%d\n",flag);
}
return 0;
}