题意:类似于成语接龙, 不过有可能会首尾相连。
定义:
欧拉回路:每条边恰好只走一次,并能回到出发点的路径
欧拉路径:经过每一条边一次,但是不要求回到起始点
欧拉回路:--无向图-- 每个节点度数都为偶数。
--有向图-- 单方向, 每个点入度==出度。
--混合图-- 暂时不知道。
欧拉路径:
--无向图-- 一个无向图存在欧拉回路,当且仅当所有顶点度数为偶数 || 除了两个度数为奇数其余都为偶数。
--有向图-- 一个有向图存在欧拉路径,当且仅当 该图所有顶点的度数为零 或者 一个顶点的度数为1,另一个度数为-1,其他顶点的度数为0。
--混合图-- lue.
本题求解欧拉路径。
#include <cmath> #include <cstdio> #include <cstring> #include <iostream> #define N 27 using namespace std; int p[N], in[N], out[N], vis[N], father[N]; void init() { for(int i = 0; i < N; i++) father[i] = i; } int Find(int a) { if(a == father[a]) return a; else return father[a] = Find(father[a]); } void Mercy(int a, int b) { int Q = Find(a); int P = Find(b); if(Q != P) father[Q] = P; } int main() { int T; scanf("%d", &T); while(T--) { int n; string s; scanf("%d", &n); init(); memset(in, 0, sizeof(in)); memset(vis, 0, sizeof(vis)); memset(out, 0, sizeof(out)); for(int i = 1; i <= n; i++) { cin >> s; int x, y; x = s[0]-'a'; y = s[s.length()-1]-'a'; out[x]++; in[y]++; Mercy(x, y); vis[x] = vis[y] = 1; } int Q = 0; for(int i = 0; i < N; i++) if(vis[i] && i==father[i]) Q++; if(Q != 1) // 判断是否连通; { printf("The door cannot be opened. "); continue; } int K = 0; for(int i = 0; i < N; i++) if(vis[i] && in[i] != out[i]) p[K++] = i; if(!K) //成环; { printf("Ordering is possible. "); continue; } if(K==2 && (out[p[0]]-in[p[0]]==1&&in[p[1]]-out[p[1]]==1 ||in[p[0]]-out[p[0]]==1&&out[p[1]]-in[p[1]]==1)) //欧拉路径判断; { printf("Ordering is possible. "); continue; } printf("The door cannot be opened. "); } return 0; }