欧拉回路与欧拉路径

    若图G中存在这样一条路径,从某个顶点出发,使得它恰通过G中每条边一次(通过每一个顶点可以多次),则称该路径为欧拉路径。若该路径是一个圈(回到起点),则称为欧拉(Euler)回路

    欧拉回路与欧拉路径的充要条件

        1)无向图存在欧拉回路的充要条件:一个无向图存在欧拉回路,当且仅当该图所有顶点度数都为偶数,且该图是连通图。

        2)有向图存在欧拉回路的充要条件:一个有向图存在欧拉回路,所有顶点的入度等于出度且该图是连通图。
   判断无向图是否存在欧拉回路:(1)图联通(dfs或者并查集判图联通)(2)所有顶点的度数均是偶数
   判断有向图是否存在欧拉回路:(1)底图(忽略边方向后的无向图)联通(2)每个顶点的入度等于出度
 
   判断无向图是否存在欧拉路径:(1)图联通(dfs或者并查集判图联通)(2)仅有2个顶点(起点和终点)的度数为奇数,其他顶点的度数均是偶数。
   判断有向图是否存在欧拉路径:(1)底图(忽略边方向后的无向图)联通(2)只有两个点的入度不等于出度,并且其中一个点出度恰好比入度大1,另一个恰好入度比出度小1,每个顶点其它每个点的入度等于出度
1.http://poj.org/problem?id=2230
本题目构建图时,每一对顶点添加两条方向相反的边。题目已经说一定具有回路,所以采用dfs从顶点1开始对边进行不重复的遍历一次即可,当所有边遍历完后,回到考虑起始点。
//---dfs求欧拉回路
#define _CRT_SECURE_NO_DEPRECATE
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
const int maxn = 10000 + 5;

struct edge{
	int v;
	bool vis;
	edge(int i = 0) :v(i){ vis = 0; }
};
vector<edge>G[maxn];

void dfs(int u){
	for (int i = 0; i < G[u].size(); i++){
		edge &e = G[u][i];
		if (!e.vis){
			e.vis = true;
			dfs(e.v);
		}
	}
	printf("%d
", u);
}

int main(){
	int u, v, m, n;
	while (~scanf("%d%d", &n, &m)){
		for (int i = 0; i <=n; i++)G[i].clear();

		for (int i = 0; i < m; i++){
			scanf("%d%d", &u, &v);
			G[u].push_back(edge(v));
			G[v].push_back(edge(u));
		}
		dfs(1);
	}

	return 0;
}

  2.http://poj.org/problem?id=2337

 首先用并查集判断是否可以构成欧拉回路。然后确定可以构成欧拉回路后再用dfs搜索出最小字典序点的欧拉道路。如果事先没有判断是否可以构成欧拉回路直接爆DFS来搜索,将会耗去大量时间。
//---dfs求欧拉回路
#define _CRT_SECURE_NO_DEPRECATE
#include<iostream>
#include<string.h>
#include<algorithm>
#include<vector>
using namespace std;
const int maxn = 1000 + 5;
const int maxsize = 26;
struct Edge{
	Edge(int a = 0, int b = 0) :v(a), id(b), vis(0){}
	int v;
	int id;//char str[maxsize];
	bool vis;
};

char str[maxn][maxsize];
int p[maxn];
int deg[26];
vector<Edge>G[maxsize];
int n;
bool ans;
int used[26];
int parent[26];

int getparent(int i){
	if (parent[i] == -1)return i;
	return parent[i] = getparent(parent[i]);
}
bool cmp(Edge a, Edge b){
	return strcmp(str[a.id], str[b.id])<0;
}

void dfs(int u, int curr){
	if (curr == n){
		ans = 1;
		printf("%s", str[p[0]]);
		for (int i = 1; i < n; i++)printf(".%s",str[p[i]]);
		printf("
");
		return;
	}
	if (ans)return;
	for (int i = 0; i < G[u].size(); i++){
		Edge&e = G[u][i];
		if (!e.vis){
			e.vis = 1;
			p[curr] = e.id;
			dfs(e.v, curr + 1);
			e.vis = 0; //撤回标志
		}
	}
}
int main(){
	int T, i, u, v;
	scanf("%d", &T);
	while (T--){
		memset(deg, 0, sizeof(deg));
		memset(used, 0, sizeof(used));
		memset(parent, -1, sizeof(parent));

		for (i = 0; i < 26; i++)G[i].clear();
		scanf("%d", &n);
		int cc = 26;//联通块;
		for (i = 0; i < n; i++){
			scanf("%s", str[i]);
			u = str[i][0] - 'a';
			v = str[i][strlen(str[i]) - 1] - 'a';
			deg[u]++; deg[v]--;
			used[u] = used[v] = 1;
			G[u].push_back(Edge(v, i));
			u = getparent(u); v = getparent(v);
			if (u != v){
				cc--;
				parent[u] = v;
			}
		}
		vector<int>d;
		for (i = 0; i < 26; i++){
			if (!used[i])cc--;
			else if (deg[i])d.push_back(deg[i]);
		}

		ans = 0;
		if (cc == 1 && (d.empty() || d.size() == 2 && (d[0] == -1 || d[0] == 1)))ans = 1;
		if (ans == 0){
			printf("***
"); continue;
		}
		for (i = 0; i < 26; i++)
			sort(G[i].begin(), G[i].end(), cmp);
		if (d.size() == 2){
			for (i = 0; i < n; i++){
				if (deg[i] == 1)break;
			}
		}
		else{
			i = 0;
			while (!used[i])i++;
		}
		ans = 0;
		dfs(i, 0);

	}
	return 0;
}

  

 
原文地址:https://www.cnblogs.com/td15980891505/p/5836798.html