欧拉回路 & 欧拉路径

欧拉路径

对于一张图 , 每条边必须且只能走一次 , 点可以无限经过 , 这样的路线就是欧拉路径

百度百科给的定义

1)欧拉路:通过图中所有边的简单路。
2)欧拉回路:闭合的欧拉路。
3)欧拉图:包含欧拉回路的图。

显然每个字母作为一个点 , 每个字母对做边 , 就是来求欧拉回路
那么怎么来求欧拉路径呐?
首先 , 如果一个点的度数是偶数才可以走入并走出 , 所以一张图的欧拉路径就与奇数度数的点有联系
奇数点就意味着一条欧拉路径到这里就可能会终结 , 当然欧拉路径也一定是从这样的点开始的
所以如果一张欧拉图只有一种欧拉路径 , 那么也就一定只有两个奇数点
但是如果没有奇数点呐 , 很显然也是一种欧拉路径 , 只不过最后就会又回到起点 , 构成欧拉回路
所以判断是不是欧拉路径就可以通过判断奇数点个数来判断
如果有解呢?
那么就可以通过DFS来遍历欧拉路径
但是还有一种情况没有判别 , 图如果不连通怎么办?
在这道题中我看有些神仙用并查集来判断
但是其实对于这道题有一种更简单的方法来判别 , 就是如果所有的字母对都符合条件的话那么显然最后答案的长度就是n + 1 (n是字母对的数量)
所以在DFS完之后检查一下长度是不是合法就可以了
另:为了方便 , 我这道题用的是邻接矩阵存图
  1 #include<set>
  2 #include<cmath>
  3 #include<cstdio>
  4 #include<cstring>
  5 #include<cstdlib>
  6 #include<iostream>
  7 #include<algorithm>
  8 #define APART puts("----------------------")
  9 #define debug 1
 10 #define FILETEST 0
 11 #define inf 150
 12 #define ll long long
 13 #define ha 998244353
 14 #define INF 0x7fffffff
 15 #define INF_T 9223372036854775807
 16 #define DEBUG printf("%s %d\n",__FUNCTION__,__LINE__)
 17 
 18 namespace chino{
 19 
 20 const char nos[] = "No Solution";
 21 
 22 inline void setting(){
 23 #if FILETEST
 24     freopen("test.in", "r", stdin);
 25     freopen("test.me.out", "w", stdout);
 26 #endif
 27     return;
 28 }
 29 
 30 inline int read(){
 31     char c = getchar(), up = c; int num = 0;
 32     for(; c < '0' || c > '9'; up = c, c = getchar());
 33     for(; c >= '0' && c <= '9'; num = (num << 3) + (num << 1) + (c ^ '0'), c = getchar());
 34     return  up == '-' ? -num : num;
 35 }
 36 
 37 int n;
 38 int cntE;
 39 int size, tot;
 40 int begin, end;
 41 int ansnow;
 42 int in[inf], out[inf];
 43 int G[inf][inf];
 44 char ans[inf * inf];
 45 
 46 inline void fail(){
 47     puts(nos);
 48     exit(0);
 49 }
 50 
 51 void DFS(int now){
 52     for(int i = 1; i <= 128; i++){
 53         if(G[now][i]){
 54             G[i][now] = 0, G[now][i] = 0;
 55             DFS(i);
 56         }
 57     }
 58     ans[++ansnow] = now;
 59     return;
 60 }
 61 
 62 inline void put(){
 63     for(int i = ansnow; i; i--)
 64         putchar(ans[i]);
 65     puts("");
 66     return;
 67 }
 68 
 69 inline int main(){
 70     n = read();
 71     char str[3] = "";
 72     for(int i = 1; i <= n; i++){
 73         std::cin >> str;
 74 #define str (int)str
 75         G[str[0]][str[1]] = 1;
 76         G[str[1]][str[0]] = 1;
 77         ++in[str[0]], ++out[str[0]];
 78         ++in[str[1]], ++out[str[1]];
 79 #undef str
 80     }
 81     for(int i = 1; i <= 128; i++)
 82         if(in[i] & 1)
 83             ++size;
 84     for(int i = 1; i <= 128; i++){
 85         if(in[i] & 1){
 86             begin = i;
 87             break;
 88         }
 89     }
 90     if(begin)
 91         goto A;
 92     for(int i = 1; i <= 128; i++)
 93         if(in[i]){
 94             begin = i;
 95             break;
 96         }
 97 A:    if(size == 2 || size == 0)
 98         DFS(begin);
 99     if(ansnow == n + 1)
100         put();
101     else fail();
102     return 0;
103 }
104 
105 }//namespace chino
106 
107 int main(){return chino::main();}

 

 另一道例题:[POI2011]SMI-Garbage

欧拉回路例题

首先这道题很显然如果结果和初始值一样就不需要连边 , 否则就连边 , 然后找到最少的欧拉回路就可以了

 欧拉回路与欧拉路径唯一的不同就是欧拉回路收尾相连 , 其他的几乎一样

这张情况下,  如果有一个点是奇数度数那么肯定就构不成欧拉回路了 , 那就直接无解

DFS中注意会有反向边 , 然后就没有啥需要注意的了吧

  1 #include<cmath>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<cstdlib>
  5 #include<iostream>
  6 #include<algorithm>
  7 #define APART puts("----------------------")
  8 #define debug 1
  9 #define FILETEST 0
 10 #define inf 2000010
 11 #define ll long long
 12 #define ha 998244353
 13 #define INF 0x7fffffff
 14 #define INF_T 9223372036854775807
 15 #define DEBUG printf("%s %d\n",__FUNCTION__,__LINE__)
 16 
 17 namespace chino{
 18 
 19 const char nos[] = "NIE";
 20 
 21 inline void setting(){
 22 #if FILETEST
 23     freopen("test.in", "r", stdin);
 24     freopen("test.me.out", "w", stdout);
 25 #endif
 26     return;
 27 }
 28 
 29 inline int read(){
 30     char c = getchar(), up = c; int num = 0;
 31     for(; c < '0' || c > '9'; up = c, c = getchar());
 32     for(; c >= '0' && c <= '9'; num = (num << 3) + (num << 1) + (c ^ '0'), c = getchar());
 33     return  up == '-' ? -num : num;
 34 }
 35 
 36 int n, m;
 37 int cntE = -1;
 38 int tot, mnt;
 39 int in[inf];
 40 int xb[inf];
 41 int vis[inf];
 42 int ans[inf];
 43 int head[inf]; 
 44 struct Edge{
 45     int to;
 46     int end;
 47     int next;
 48     int begin;
 49 }e[inf << 1];
 50 
 51 inline void AddEdge(int from, int to, int begin, int end){
 52     ++cntE;
 53     e[cntE].to = to;
 54     e[cntE].begin = begin;
 55     e[cntE].end = end;
 56     e[cntE].next = head[from];
 57     head[from] = cntE;
 58     return;
 59 }
 60 
 61 inline void fail(){
 62     puts(nos);
 63     exit(0);
 64 }
 65 
 66 void DFS(int now, int root){
 67     ans[++mnt] = now;
 68     in[now] -= 2;
 69     for(int i = head[now]; i ^ -1; i = e[i].next){
 70         if(vis[i] || vis[i ^ 1])
 71             continue;
 72         vis[i] = 1, vis[i ^ 1] = 1;
 73         if(e[i].to == root){
 74             ans[++mnt] = root;
 75             return;
 76         }
 77         DFS(e[i].to, root);
 78         return;
 79     }
 80     return;
 81 }
 82 
 83 inline int main(){
 84     memset(head, -1, sizeof head);
 85     n = read();
 86     m = read();
 87     for(int i = 1; i <= m; i++){
 88         int u = read();
 89         int v = read();
 90         int begin = read();
 91         int end = read();
 92         if(begin == end)
 93             continue;
 94         AddEdge(u, v, begin, end);
 95         AddEdge(v, u, begin, end);
 96         ++in[u], ++in[v];
 97     }
 98     for(int i = 1; i <= n; i++){
 99         if(in[i] & 1)
100             fail();
101     }
102     for(int i = 1; i <= n; i++){
103         if(in[i]){
104             DFS(i, i);
105             ++tot;
106             xb[tot] = mnt;
107         }
108     }
109     printf("%d\n", tot);
110     for(int i = 1; i <= tot; i++){
111         printf("%d ", xb[i] - xb[i - 1] - 1);
112         for(int j = xb[i - 1] + 1; j <= xb[i]; j++)
113             printf("%d ", ans[j]);
114         puts("");
115     }
116     return 0;
117 }
118 
119 }//namespace chino
120 
121 int main(){return chino::main();}

 

转载于:https://www.cnblogs.com/chiarochinoful/p/algorithm-Euler-path-and-circuit.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值