HDU 1116 - Play on Words (并查集 + 欧拉路)
题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=1116
题目大意:给你n个字符串,判断是否能够全部成功接龙 aXXXXb - bXXXXc - cXXXXf - fXXXXe ·······
整体思路:此题可看作一个有向图,每一个字符串看作一条边,首字母和尾字母分别是两点。判断此图是否存在欧拉通路,是否为连通图。若为存在欧拉通路的连通图,则满足题意。
所以我们首先可以利用并查集判断其是否为连通图,如不连通,直接输出门无法打开。然后由有向图的欧拉通路的判断条件,找出所有边的出度与入度。得出题目结果
有向图是否存在欧拉路和欧拉回路判断条件:把一个点上的出度记为1、入度记为-1,这个点上所有的出度与入度相加即为它的度数。如果一个有向图只有一个度数为1的点、一个度数为-1的点,其他所有点的度数为0,那么存在欧拉路径,其中度数为1的是起点、度数为-1的是终点。当且仅当该图所有点的度数为0,存在欧拉回路。
代码:
#include<bits/stdc++.h> using namespace std; const int maxn = 30; string s; int in[maxn], ou[maxn], vis[maxn], f[maxn]; int find(int s) { return s == f[s] ? s : find(f[s]); } int main() { int T, n; cin >> T; while(T--) { cin >> n; memset(in,0,sizeof(in)); memset(ou,0,sizeof(ou)); memset(vis,0,sizeof(vis)); for(int i = 1; i <= maxn; i++) f[i] = i; int x, y, z; for(int i = 0; i < n; i++) { cin >> s; x = s[0] - 'a'; y = s[s.size()-1] - 'a'; in[x]++; ou[y]++; f[x] = f[y] = find(x); vis[x] = vis[y] = 1; } int r = 0; for(int i = 0; i < maxn; i++) { if(vis[i] && f[i] == i) r++; } if(r > 1) { //1个根节点 cout << "The door cannot be opened." << endl; continue; } bool flag = false; x = 0, y = 0, z = 0; for(int i = 0; i < maxn; i++) { if(vis[i] && in[i] != ou[i]) { if(in[i] == ou[i]-1) x++; else if(in[i] == ou[i]+1) y++; else z++; } } if(z) { cout << "The door cannot be opened." << endl; continue; } if((x == 1 && y == 1) || (x == 0 && y == 0)) { cout << "Ordering is possible." << endl; }else cout << "The door cannot be opened." << endl; } return 0; }