首页 > 代码库 > UVa 10129 (并查集 + 欧拉路径) Play on Words
UVa 10129 (并查集 + 欧拉路径) Play on Words
题意:
有n个由小写字母的单词,要求判断是否存在某种排列是的相邻的两个单词,前一个单词末字母与后一个单词首字母相同。
分析:
将单词的两个字母看做节点,则一个单词可以看做一条有向边。那么题中所求的排列就等价于该有向图中是否存在欧拉路径。
在判断之前,首先要确定这个图是连通的,代码中用并查集来实现。
回顾一下存在欧拉路径的条件,全都是偶点或者有且仅有两个奇点。我们用deg来记录每个点的度,出度为1,入度为-1。
程序中判断存在欧拉路径的条件就是:deg全为0 或者 有两个不为0的,其中一个为1一个为-1
used记录某个字母是否出现过。
1 //#define LOCAL 2 #include <vector> 3 #include <cstdio> 4 #include <cstring> 5 using namespace std; 6 7 const int maxn = 1000 + 10; 8 char word[maxn]; 9 int pa[256], deg[256], cc, used[256];10 11 int find(int a)12 { return pa[a] == a ? a : pa[a] = find(pa[a]); }13 14 int main(void)15 {16 #ifdef LOCAL17 freopen("10129in.txt", "r", stdin);18 #endif19 20 int T, n;21 scanf("%d", &T);22 while(T--)23 {24 memset(used, 0, sizeof(used));25 memset(deg, 0, sizeof(deg));26 for(int i = ‘a‘; i <= ‘z‘; ++i)27 pa[i] = i;28 cc = 26; //Á¬Í¨¿éµÄÊýÁ¿ 29 30 scanf("%d", &n);31 for(int i = 0; i < n; ++i)32 {33 scanf("%s", word);34 char c1 = word[0];35 char c2 = word[strlen(word) - 1];36 used[c1] = used[c2] = 1;37 deg[c1]++; deg[c2]--;38 int p1 = find(c1);39 int p2 = find(c2);40 if(p1 != p2)41 {42 cc--;43 pa[p1] = p2;44 }45 }46 47 vector<int> d;48 for(int i = ‘a‘; i <= ‘z‘; ++i)49 {50 if(!used[i]) --cc;51 else if(deg[i]) d.push_back(i);52 }53 bool ok = false;54 if(cc == 1 && (d.empty() || (d.size() == 2 && (deg[d[0]] == 1 || deg[d[0]] == -1)))) ok = true;55 if(ok) puts("Ordering is possible.");56 else puts("The door cannot be opened.");57 }58 59 return 0;60 }
UVa 10129 (并查集 + 欧拉路径) Play on Words
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。