欧拉回路

定义

如果图G中的一个路径包括每个边恰好一次,则该路径称为欧拉路径(Euler path)。
如果一个回路是欧拉路径,则称为欧拉回路(Euler circuit)。
具有欧拉回路的图称为欧拉图(简称E图)。具有欧拉路径但不具有欧拉回路的图称为半欧拉图。


判定

有向图回路:图联通 & & \&\& && 每个点入度 = = = 出度
无向图回路:图联通 & & \&\& && 每个点的度数为偶数

有向图通路:图联通 & & \&\& && 每个点入度 = = = 出度
      或者可以存在两个点,其中一个出度比入度大 1 1 1,为路径的起点
      另外一个入度比出度大 1 1 1,为路径的终点
无向图通路:图联通 & & \&\& && 度数为奇数的的点只有 2 2 2 个或者 0 0 0
      当有两个奇点时,一个为起点,另一个为终点


欧拉回路 输出

从起点开始找一条回路
找出有尚未访问的边的路径上的第一个顶点, 并执行另外一次深度优先搜索
这将给出另外一个回路, 把它拼接到原来的回路上
继续该过程直到所有的边都被遍历为止

模板题:UOJ #117. 欧拉回路
s o l v e 1 solve1 solve1 为无向图回路, s o l v e 2 solve2 solve2 为有向图回路

#include<bits/stdc++.h>
#define rint register int
#define deb(x) cerr<<#x<<" = "<<(x)<<'\n';
using namespace std;
typedef long long ll;
typedef pair <int,int> pii;
const int maxn = 1e6 + 5;
int T, n, m;

bool solve1() {		//	无向图 
	scanf("%d%d", &n, &m);
	vector <vector <pii> > g(2 * n + 5);
	for(int i=1, u, v; i<=m; i++) {
		scanf("%d%d", &u, &v);
		g[u].push_back({v, i});
		g[v].push_back({u, -i});
	}
	for(int i=1; i<=n; i++)
		if(g[i].size() & 1) return printf("NO\n"), 0;
	vector <bool> del(m + 5);
	vector <int> ans;
	function <void(int, int)> dfs = [&] (int u, int fa) {
		while(g[u].size()) {
			auto it = g[u].back(); g[u].pop_back();
			int v = it.first, id = it.second;
			if(!del[abs(id)]) {
				del[abs(id)] = true;
				dfs(v, id);
			}
		}
		if(fa != 0) ans.push_back(fa);
	};
	for(int i=1; i<=n; i++)
		if(g[i].size()) {
			dfs(i, 0);
			break;
		}
	if(ans.size() != m) return printf("NO\n"), 0;
	printf("YES\n");
	for(int i=ans.size()-1; ~i; i--)
		printf("%d ", ans[i]);
}

bool solve2() {		//	有向图 
	scanf("%d%d", &n, &m);
	vector <int> in(n + 5), out(n + 5);
	vector <vector <pii> > g(2 * n + 5);
	for(int i=1, u, v; i<=m; i++) {
		scanf("%d%d", &u, &v);
		g[u].push_back({v, i});
		in[v]++, out[u]++;
	}
	for(int i=1; i<=n; i++)
		if(in[i] ^ out[i]) return printf("NO\n"), 0;
	vector <bool> del(m + 5);
	vector <int> ans;
	function <void(int, int)> dfs = [&] (int u, int fa) {
		while(g[u].size()) {
			auto it = g[u].back(); g[u].pop_back();
			int v = it.first, id = it.second;
			if(!del[id]) {
				del[id] = true;
				dfs(v, id);
			};
		}
		if(fa != 0) ans.push_back(fa);
	};
	for(int i=1; i<=n; i++)
		if(g[i].size()) {
			dfs(i, 0);
			break;
		}
	if(ans.size() != m) return printf("NO\n"), 0;
	printf("YES\n");
	for(int i=ans.size()-1; ~i; i--)
		printf("%d ", ans[i]);
}

signed main() {
	scanf("%d", &T);
	T == 1 ? solve1() : solve2();
}

欧拉通路 输出

模板题:HihoCoder - 1181
输出欧拉路径(无向图)

#include<bits/stdc++.h>
#define rint register int
#define deb(x) cerr<<#x<<" = "<<(x)<<'\n';
using namespace std;
typedef long long ll;
typedef pair <int,int> pii;
const int maxn = 1e6 + 5;
int T, n, m;

signed main() {
	scanf("%d%d", &n, &m);
	vector <vector <pii> > g(2 * n + 5);
	for(int i=1, u, v; i<=m; i++) {
		scanf("%d%d", &u, &v);
		g[u].push_back({v, i});
		g[v].push_back({u, -i});
	}
	int st = 1; 
	for(int i=1; i<=n; i++)
		if(g[i].size() & 1) st = i;
	vector <bool> del(m + 5);
	vector <int> ans;
	function <void(int, int)> dfs = [&] (int u, int fa) {
		while(g[u].size()) {
			auto it = g[u].back(); g[u].pop_back();
			int v = it.first, id = it.second;
			if(!del[abs(id)]) {
				del[abs(id)] = true;
				dfs(v, id);
			}
		}
		ans.push_back(u);
	};
	for(int i=1; i<=n; i++)
		if(g[i].size()) {
			dfs(st, 0);
			break;
		}
	for(int i=ans.size()-1; ~i; i--)
		printf("%d ", ans[i]);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值