UVA10129 POJ1386 HDU1116 ZOJ2016 Play on Words【欧拉回路+并查集】
问题链接:UVA10129 POJ1386 HDU1116 ZOJ2016 Play on Words。
问题简述:先输入测试用例数T,每个测试用例包括整数N和N个单词数,问这些单词首尾字母能否接成一条龙?
问题分析:这是一个单词接龙问题,一个单词的尾字母和另外一个单词的首字母相同则可以接成龙。其中,每个单词只包含小写字母。单词的首字母和尾字母可以作为图的一个结点,从单词的首字母到尾字母画一条有向边,单词接龙问题就变成一笔画问题,或称为欧拉路径问题。
欧拉路径问题有两个条件,一是图是联通的;二是所有结点出入度相同,或者只有两个结点出入度差为1。
程序说明:用并查集来判定图是否是联通的。
程序提交后,除了POJ1386出现TLE,其他3个在线评判都AC了。在高人指点之下,程序中增加了69行的代码“ios::sync_with_stdio(false);”,就都可以通过了。这是由于C++的输入输出比较慢的原因,通过这行代码,改善了I/O的速度。
这个语句也可以写为“std::ios::sync_with_stdio(false);”。担心C++输入输出慢,可以使用该语句改善速度。
AC的C++语言程序如下:
/* UVA10129 Play on Words */ #include <iostream> #include <string> #include <cstring> using namespace std; const int N = 26; // 并查集类 int v[N]; class UF { private: int length; public: UF(int n) { length = n; for(int i=0; i<=n; i++) v[i] = i; } // 压缩 int Find(int x) { if(x == v[x]) return x; else return v[x] = Find(v[x]); } bool Union(int x, int y) { x = Find(x); y = Find(y); if(x == y) { return false; } else { v[x] = y; return true; } } }; int degreeout[N]; int degreein[N]; // 出入度检查:return nopathflag bool degreeincheck() { int startcount = 0, endcount = 0; for(int i=0; i<N; i++) if(degreeout[i] != degreein[i]) { if((degreeout[i] - degreein[i]) == 1) { if(++startcount > 1) return true; } else if((degreeout[i] - degreein[i]) == -1) { if(++endcount > 1) return true; } else return true; } return false; } int main() { int t, n, src, dest; ios::sync_with_stdio(false); cin >> t; while(t--) { UF uf(N+1); memset(degreeout, 0, sizeof(degreeout)); memset(degreein, 0, sizeof(degreein)); // 输入测试用例的数据,构建并查集,统计各个结点的度 cin >> n; string s; while(n--) { cin >> s; src = s[0] - 'a'; dest = s[s.size() - 1] - 'a'; degreeout[src]++; degreein[dest]++; uf.Union(src, dest); } // 判断图的联通性 bool nopathflag = false; int root = -1; for(int i=0; i<N; i++) { if(degreeout[i] || degreein[i]) { if(root == -1) root = uf.Find(i); else if(uf.Find(i) != root) { nopathflag = true; break; } } } // 判定是否存在欧拉路径:出入度检查 if(!nopathflag) nopathflag = degreeincheck(); // 输出结果 if(nopathflag) cout << "The door cannot be opened." << endl; else cout << "Ordering is possible." << endl; } return 0; }