1. 程式人生 > >UASCO 3.3 Riding the Fences 騎馬修柵欄

UASCO 3.3 Riding the Fences 騎馬修柵欄

題目大意

無向連通圖,求尤拉路徑。

樣例輸入&輸出

sample input

一個m,道路數,m對數,路的兩個端點。

9

1 2 2 3 3 4 4 2 4 5 2 5 5 6 5 7 4 6 

sample output

字典序走的路徑

1 2 3 4 2 5 4 6 5 7

分析&反思

一開始大陸暴力dfs,4個點。後來瞭解到了新演算法 fleury 佛羅萊演算法。

目前還不大理解,但模板挺好背的。

先複習一下尤拉路徑和歐拉回路。

尤拉路徑:不重複走邊,走完所有的邊。

                 條件:度數為奇的點小於2,必從奇點出發,或必回到奇點。若有向圖則是入讀比出度大1和入度比出度大1的兩個點。

歐拉回路:不重複走邊,走完所有的邊,且回到出發點。

                 條件:無奇點。

此外,如果沒有奇點,從任意點出發都可以得到解。

fleury演算法就是。。。建立一個棧,先把起點放進去,開始迴圈。取棧頂彈出,如果無路可走(路都被走過了),就加入答案序列。若有路可走,dfs這個點,一路走並標記路,將走過的點加入棧,直到走不動(根據我的理解。。。dfs後可以得到一個橋對面的連通塊)。

算了我還是以後理解了再補吧。

程式碼

/*
ID:changsz1
LANG:C++
TASK:fence
*/

#include<cstdio>
#include<iostream>
using namespace std;

const int maxn = 503;

int n1 = 1000000000, n2, m, map[maxn][maxn], du[maxn];

int ans[maxn*3], cnt;

int stack[maxn*3], top;

void dfs(int x) {
	stack[++top] = x;
	for(int i = n1; i <= n2; i++) {
		if(map[x][i]) {
			map[x][i]--;
			map[i][x]--;
			dfs(i);
			break;
		}
	}
	return;
}

void fleury(int u) {
	int flag = 0;
	stack[++top] = u;
	while(top) {
		flag = 0;
		u = stack[top--];
		for(int v = n1; v <= n2; v++) {
			if(map[u][v]) {
				flag = 1;
				break;
			}
		}
		if(flag) dfs(u);
		else ans[++cnt] = u;
	}
}

int main() {
	freopen("fence.in", "r", stdin);
	freopen("fence.out", "w", stdout);
	
	scanf("%d", &m);
	
	for(int i = 1, u, v; i <= m; i++) {
		scanf("%d%d", &u, &v);
		map[u][v]++; 
		map[v][u]++;//存在重邊
		n1 = min(n1, min(u, v));
		n2 = max(n2, max(v, u));
		du[v]++;
		du[u]++;
	}
	
	int ji = 0;
	for(int i = n1; i <= n2; i++) if(du[i]%2 == 1) ji++;
	
	if(!ji) fleury(n1);
	else for(int i = n1; i <= n2; i++) if(du[i]%2 == 1) fleury(i);
	
	for(int i = m+1; i; i--) printf("%d\n", ans[i]);
	
	return 0;
}