欧拉路径
对于一张图 , 每条边必须且只能走一次 , 点可以无限经过 , 这样的路线就是欧拉路径
百度百科给的定义
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();}
欧拉回路例题
首先这道题很显然如果结果和初始值一样就不需要连边 , 否则就连边 , 然后找到最少的欧拉回路就可以了
欧拉回路与欧拉路径唯一的不同就是欧拉回路收尾相连 , 其他的几乎一样
这张情况下, 如果有一个点是奇数度数那么肯定就构不成欧拉回路了 , 那就直接无解
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();}