简介
欧拉回路就是给一个图,存在一条回路把所边经过且每条边只经过一次。
存在欧拉回路的条件
- 对于无向图:
存在欧拉回路的条件:每个点的度都为偶数;
存在欧拉路的条件:有且只有两个点的度为一,且这两个点分别为起点和终点;
- 对于有向图:
存在欧拉回路的条件:每个点出度等于入度;
存在欧拉路的条件:存在一个点出度比入度多一作为起点,存在一点入度比出度多一作为终点,其余点出度等于入度;
套圈法
判断是否存在欧拉回路很好判断,那怎么求欧拉回路呢?
我们采用套圈法,dfs回溯的时候才把边倒着记录。为什么要这样呢?
假如我们随便走,有一条边加一条边,最后回到起始点,会形成一个环。但是我们不能保证没有其他环还没遍历到!
下面拿个图演示一波:
红色为起始点,蓝色为有向边,随便走的话我们可能走完左边的圈就不走了,右边的圈还没走。
而套圈法则是,如果我们遇到分叉点就都走一走,这样能保证每条边都走过,最后倒着加边即可。
注意每条边只走一次,每次走完一条边我们要标记走过,这样就能保证复杂度。
复杂度嘛,每条边只走一次,复杂度是。
下面以洛谷P1127词链(这是链接)一题作为例题。
代码如下
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
using namespace std;
struct node{
int a, b;
char s[25];
bool operator < (const node & A) const{
return strcmp(s, A.s) < 0;
}
}d[1005];
int du[1005], cnt, v[1005], x[1005], ans[1005], p, m;
void dfs(int a, int id){
int i = x[a], b;
while(d[i].a == a){
if(!v[i]){
v[i] = 1;
dfs(d[i].b, i);
}
i++;
}
ans[++m] = id;
}
int main(){
int i, j, n, a, b, c;
scanf("%d", &n);
for(i = 1; i <= n; i++){
scanf("%s", d[i].s);
c = strlen(d[i].s);
d[i].a = d[i].s[0];
d[i].b = d[i].s[c-1];
}
sort(d + 1, d + i);
for(i = 1; i <= n; i++){
du[d[i].a]++, du[d[i].b]++;
}
for(i = 'z'; i >= 'a'; i--) if(du[i] & 1) cnt++, p = i;
if(cnt == 1 || cnt > 2){
printf("***");
return 0;
}
if(!p) p = d[1].a;
for(i = n; i >= 1; i--) x[d[i].a] = i;
dfs(p, x[p]);
if(m != n + 1){
printf("***");
return 0;
}
for(i = m-1; i > 1; i--) printf("%s.", d[ans[i]].s);
printf("%s", d[ans[1]].s);
return 0;
}
来源:https://blog.csdn.net/iamhpp/article/details/98733811