首页 > 其他 > 详细

欧拉回路&【洛谷习题】无序字母对

时间:2018-08-24 22:10:23      阅读:392      评论:0      收藏:0      [点我收藏+]

首先非常痛心疾首地说一句,欧拉回路自己之前只是看过代码,知道思想,从来没有亲手实现过,所以,,,伤亡惨重!!!

欧拉回路是一个非常有意思的图论模型,因为伟大的数学家欧拉(euler)而得名。传说,曾经人们沉迷于一个七桥问题,想找出一种走法不重复地经过七座桥(具体请自行了解)。欧拉指出了不存在这样的走法,并由此归结出了“一笔画问题”。用图论的语言来说,就是找一条路径不重复地走过所有的边。

实际上,从一个点出发,不重复地经过所有的边,这叫做欧拉道路;如果这条路径起点和终点相同,才称为欧拉回路。另外,如果一个图存在欧拉道路,那么称为半欧拉图,如果一个图存在欧拉回路,称为欧拉图。

对于无向图,存在欧拉道路的条件是只有两个或不存在奇点(度为奇数的点),存在欧拉回路的条件是不存在奇点。对于有向图,存在欧拉道路的条件是只有两个点的入度和出度不相同,并且其中一个点(起点)的出度比入度大1,另一个点(终点)的入度比出度大1,或者所有点的入度和出度都相等,存在欧拉回路的条件是所有点的入度和出度都相等。当然图必须是连通的。

寻找欧拉道路或者欧拉回路是比较简单的,可以使用DFS。起点的确定也需要注意,如果找欧拉道路,必须找到相应的起点,而欧拉回路任选一个点作为起点即可。

技术分享图片
1 void euler(int u) {
2     for(int v=1;v<=n;++v)
3         if(G[u][v]) {
4             G[u][v]=G[v][u]=0; //有向图则改为G[u][v]=0;
5             euler(v);
6         }
7     ans.push(u);
8 }
寻找欧拉道路或欧拉回路(无向图)

需要注意的是,我们此处标记的是边(或者删除边)。因为欧拉道路或欧拉回路是可以一口气走到结束的,所以上面的代码可以放心写个循环,且递归后不必跳出,因为当返回该点时,该点所连的其他边必然已经被走过了。因此答案里存的就是一条完整的路径。

 

无序字母对:https://www.luogu.org/problemnew/show/P1341


 

这道题的话,还是浪费了很多时间,一是因为欧拉回路以前没写过,而是因为这道题答案保存那里有点玄学问题,默默改成栈就过了。字符的处理也需要注意一下。

技术分享图片
 1 #include<cstdio>
 2 #include<stack>
 3 using namespace std;
 4 const int maxn=55;
 5 int n,G[maxn][maxn],d[maxn];
 6 stack<int> ans; //用栈倒序保存答案
 7 int toInt(char c) { //字符转为整数
 8     if(c>=A&&c<=Z) return c-A+1;
 9     return c-a+27;
10 }
11 char toChar(int i) { //整数转为字符
12     if(i>=1&&i<=26) return i-1+A;
13     return i-27+a;
14 }
15 void euler(int u) {
16     for(int v=1;v<=52;++v)
17         if(G[u][v]) {
18             G[u][v]=G[v][u]=0; //删边
19             euler(v);
20         }
21     ans.push(u);
22 }
23 int main() {
24     scanf("%d",&n);
25     char cu,cv;
26     int u,v;
27     for(int i=1;i<=n;++i) {
28         while((cu=getchar())==\n||cu== ||cu==\r); //过滤无用字符
29         cv=getchar();
30         u=toInt(cu),v=toInt(cv);
31         G[u][v]=G[v][u]=1;
32         ++d[u],++d[v]; //统计度数
33     }
34     int s=0,cnt=0;
35     for(int i=1;i<=52;++i) //找起点和判断是否存在欧拉道路
36         if(d[i]&1) {
37             ++cnt;
38             if(!s) s=i;
39         }
40     if(!cnt) for(int i=1;i<=52;++i)
41         if(d[i]) {
42             s=i;
43             break;
44         }
45     if(cnt&&cnt!=2) {
46         printf("No Solution\n");
47         return 0;
48     }
49     euler(s);
50     if((int)ans.size()<n+1) printf("No Solution");
51     while(!ans.empty()) {
52         int p=ans.top();
53         ans.pop();
54         printf("%c",toChar(p));
55     }
56     putchar(\n);
57     return 0;
58 }
AC代码

 

欧拉回路&【洛谷习题】无序字母对

原文:https://www.cnblogs.com/Mr94Kevin/p/9532164.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!