欧拉回路(一笔画问题):
求度数>>连通性>>遍历找回路
题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=19451
欧拉回路:
有0个或2个奇度数点,则一定有欧拉回路。
求度数>>连通性>>遍历找回路
求度数:
1.设置两个数组在输入时判断。(推荐)
2.反向查找图。
连通性:
只需要判断无向图的连通性,遍历之后配合审查函数,审查函数配合出入度数组。
有向图如要利用保存的图,可以将图的反向设置为–,正向为++。
根据规模和应用方法灵活运用矩阵和vector动态存图,可以有限矩阵保存。
其它理解见我的注释:
#include <cstdio>
#include <cstring>
using namespace std;
#define MAX_V 26
#define MAX_LEN 1005
int G[MAX_V][MAX_V];
int inDeg[MAX_V];
int outDeg[MAX_V];
int vis[MAX_V];
void DFS(int);
bool okDeg();
bool okDFS();
int main()
{
int cases;
scanf("%d", &cases);
while (cases--) {
// init
memset(G, 0, sizeof(G));
memset(inDeg, 0, sizeof(inDeg));
memset(outDeg, 0, sizeof(outDeg));
memset(vis, 0, sizeof(vis));
int edge, star;
scanf("%d%*c", &edge);
// enter
for (int i = 0; i < edge; i++) {
char str[MAX_LEN];
gets(str);
int u = str[0] - 'a';
int v = str[strlen(str) - 1] - 'a';
outDeg[u]++;
inDeg[v]++;
G[u][v]++;
G[v][u]++;
star = u;
}
// judge
DFS(star);
if (okDeg() && okDFS()) {
printf("Ordering is possible.\n");
}else {
printf("The door cannot be opened.\n");
}
// end a case
}
return 0;
}
void DFS(int u) //遍历整个图,配合okDFS判断无向图的连通性
{
vis[u] = true;
for (int i = 0; i < MAX_V; i++) {
if (G[u][i] > 0) {
G[u][i]--;
G[i][u]--;
DFS(i);
}
}
}
bool okDeg()
{
bool markStar = false;
bool markEnd = false;
for (int i = 0; i < MAX_V; i++) {
if (inDeg[i] != outDeg[i]) {
if (!markEnd && inDeg[i] == outDeg[i] + 1) {
markEnd = true;
}else if (!markStar && inDeg[i] + 1 == outDeg[i]){
markStar = true;
}else {
return false;
}
}
}
return true;
}
bool okDFS() //配合DFS判断无向图的连通性
{
for (int u = 0; u < MAX_V; u++) {
if (inDeg[u] + outDeg[u]) { //确定这个节点存在
if (vis[u] == false) {
return false;
}
}
}
return true;
}
这道题没有涉及欧拉回路的遍历,于是我额外贴上刘汝佳的代码。
void euler(int u)//遍历,有向图需要找到起点
{
for(int v = 0; v < n; ++v)
if(G[u][v] && !vis[u][v])//节点存在且未访问
{
vis[u][v] = vis[v][u] = 1;//标记访问过
euler(v);//先遍历后压栈
printf("%d %d\n",u,v);//压栈,当提前出局也压栈,一定是最后一条路
}
}
这份代码是在网上找的可读性比较高的一份ac代码,当然这篇blog的注释和讲解是我自己的理解。
http://blog.csdn.net/mistkafka/article/details/9345877