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
#include
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;
}

 

你可能感兴趣的:(USACO,图论)