歐拉路與歐拉回路 && UOJ #117. 歐拉回路

下面的定義都是個人理解
歐拉路:從一個點走到另外一個點,圖中每條邊都只經過一次
歐拉回路:在歐拉路的基礎上,要求終點和起點相同

歐拉路與歐拉回路的判斷

對於無向圖

  • 只有兩個點的度數是1,這兩個點分別爲起點和終點,則這個無向圖存在歐拉路
  • 每個點的度數都爲偶數,則這個無向圖存在歐拉回路

對於有向圖

  • 有一個點的入度比出度多1作爲終點,還有一個點的出度比入度多1作爲起點,其餘點的入度和出度相同,則這個有向圖存在歐拉路
  • 所有點的入度和出度相同,則這個有向圖存在歐拉回路

求歐拉回路

網上都是用的一種dfs的方法,也叫套圓法,名字和算法流程有關
主要流程就是標記走過的點,找到一個環不能往下走時回溯,再通過還沒走過的點找另外一個環,把這些環接起來就是歐拉回路,可以用當前弧優化,就是走過這條邊之後就不再走了

例題:UOJ #117. 歐拉回路
這就是上面算法的代碼實現
其中在加邊上用到了一些小技巧,讓標記邊的時候更方便

#include <bits/stdc++.h>
#define A 1000010

using namespace std;
typedef long long ll;
struct node {int next, to, w;}e[A];
int head[A], num = 1;
void add(int fr, int to, int w) {e[++num].next = head[fr]; e[num].to = to; e[num].w = w; head[fr] = num;}
int t, n, m, a, b, in[A], out[A], cnt, ans[A]; bool vis[A];
void dfs(int fr) {
	for (int &i = head[fr]; i; i = e[i].next) {
		node t = e[i];
		if (vis[i >> 1]) continue;
		vis[i >> 1] = 1;
		dfs(t.to);
		ans[++cnt] = t.w;
	}
}

int main(int argc, char const *argv[]) {
	cin >> t >> n >> m;
	for (int i = 1; i <= m; i++) {
		scanf("%d%d", &a, &b);
		add(a, b, i); in[b]++; out[a]++;
		if (t == 1) add(b, a, -i); else num++;
	}
	bool ok = 1;
	if (t == 1) {
		for (int i = 1; i <= n; i++) if ((in[i] + out[i]) % 2) {ok = 0; break;}
	}
	else for (int i = 1; i <= n; i++) if (in[i] != out[i]) {ok = 0; break;}
	if (ok) {
		dfs(a);
		if (cnt != m) puts("NO");
		else {
			puts("YES");
			for (int i = cnt; i >= 1; i--) printf("%d ", ans[i]);
		}
	}
	else puts("NO");
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章