题目

输入n(n≤100000)个单词,是否可以把所有这些单词排成一个序列,使得每个单词的第一个字母和上一个单词的最后一个字母相同(例如 acm,malform,mouse)。每个单词最多包含1000个小写字母。输入中可以有重复单词。

解题思路

把字母看作结点,单词看作有向边,则问题有解等价于图中存在欧拉道路。有向图中存在欧拉道路的条件有两个:一是底图(忽略边的方向后得到的无向图)连通,二是度数满足不存在奇点或奇点数为2。度数判读只要在输入时记录每个顶点的入度出度,而连通性判断有两种:DFS和并查集。

代码实现

dfs判断连通性+特判入出度

  1. #include<stdio.h>
  2. #include<cstring>
  3. using namespace std;
  4.  
  5. const int maxn = + ;
  6. int G[maxn][maxn],in[maxn],out[maxn];
  7. int vis[maxn]; //点是否访问,不是边
  8. int n;
  9. char word[ + ];
  10.  
  11. void dfs(int u)
  12. {
  13. vis[u] = ;
  14. for (int v = ; v < maxn; v++) if (G[u][v])
  15. {
  16. G[u][v] = G[v][u] = ;
  17. //G[u][v]--; G[v][u]--;
  18. dfs(v);
  19. }
  20. }
  21.  
  22. int main()
  23. {
  24. int T;
  25. scanf("%d", &T);
  26. while (T--)
  27. {
  28. memset(G, , sizeof(G));
  29. memset(in, , sizeof(in));
  30. memset(out, , sizeof(out));
  31. memset(vis, , sizeof(vis));
  32. scanf("%d", &n);
  33. int start; //起点
  34. while (n--)
  35. {
  36. scanf("%s", word);
  37. int len = strlen(word);
  38. int u = word[] - 'a', v = word[len - ] - 'a';
  39. start = u;
  40. vis[u] = vis[v] = -; //出现过的标为-1
  41. G[u][v] = G[v][u] = ; //连通性按无向图处理
  42. //G[u][v]++; G[v][u]++;
  43. out[u]++; //度数按有向图处理
  44. in[v]++;
  45. }
  46.  
  47. bool flag = true; //满足要求为true
  48. int s_odd = ,t_odd = ; //起始奇点、结束奇点
  49. for (int i = ; i < maxn; i++)
  50. {
  51. if (in[i] == out[i]) continue;
  52. if (out[i] == in[i] + && !s_odd) { start = i; s_odd = ; }
  53. else if (in[i] == out[i] + && !t_odd) t_odd = ;
  54. else { flag = false; break; }
  55. }
  56. if (flag)
  57. {
  58. dfs(start); //也可以不从奇点出发,这个只是判断连通性
  59. for (int i = ; i < maxn; i++)
  60. if (vis[i] == -) { flag = false; break; }
  61. }
  62.  
  63. if (flag) printf("Ordering is possible.\n");
  64. else printf("The door cannot be opened.\n");
  65. }
  66. return ;
  67. }

并查集判断连通性+特判入出度

  1. #include<stdio.h>
  2. #include<iostream>
  3. #include<algorithm>
  4. #include<cstring>
  5. #include<string>
  6. #include<cmath>
  7. using namespace std;
  8.  
  9. const int maxn = + ;
  10. int in[maxn], out[maxn], flag[maxn], p[maxn], fa[maxn];
  11. int n;
  12.  
  13. void init()
  14. {
  15. for (int i = ; i < ; i++)
  16. fa[i] = i;
  17. memset(in, , sizeof(in));
  18. memset(out, , sizeof(out));
  19. memset(flag, , sizeof(flag));
  20. memset(p, , sizeof(p));
  21. }
  22. int find(int x)
  23. {
  24. if (fa[x] != x) return fa[x] = find(fa[x]);
  25. return fa[x];
  26. }
  27.  
  28. void unite(int x, int y)
  29. {
  30. int rx = find(x);
  31. int ry = find(y);
  32. fa[rx] = ry;
  33. }
  34.  
  35. int main()
  36. {
  37. int T;
  38. int a, b;
  39. string str;
  40. scanf("%d", &T);
  41. while (T--)
  42. {
  43. init();
  44. scanf("%d", &n);
  45. for (int i = ; i < n; i++)
  46. {
  47. cin >> str;
  48. a = str[] - 'a';
  49. b = str[str.size() - ] - 'a';
  50. unite(a, b);
  51. in[a]++;
  52. out[b]++;
  53. flag[a] = flag[b] = ;
  54. }
  55.  
  56. int cnt = ; //记录连通分量
  57. int root;
  58. for (int i = ; i < ; i++)
  59. {
  60. if (flag[i])
  61. {
  62. root = find(i);
  63. break;
  64. }
  65. }
  66. for (int i = ; i < ; i++)
  67. {
  68. if (flag[i])
  69. if (root != find(i)) cnt = ;
  70. }
  71.  
  72. if (cnt) {
  73. printf("The door cannot be opened.\n");
  74. continue;
  75. }
  76.  
  77. int k = ; //p[i]记录度数不等的
  78. for (int i = ; i < ; i++)
  79. {
  80. if (flag[i] && in[i] != out[i]) p[k++] = i;
  81. }
  82. if (k == )
  83. {
  84. printf("Ordering is possible.\n");
  85. continue;
  86. }
  87. if (k == && (in[p[]] - out[p[]] == && in[p[]] - out[p[]] == -) || (in[p[]] - out[p[]] == - && in[p[]] - out[p[]] == ))
  88. {
  89. printf("Ordering is possible.\n");
  90. continue;
  91. }
  92. else
  93. {
  94. printf("The door cannot be opened.\n");
  95. }
  96. }
  97. return ;
  98. }

参考链接:https://blog.csdn.net/qq_29169749/article/details/51111377

UVA10129———欧拉道路的更多相关文章

  1. UVA-10129 Play on Words (判断欧拉道路的存在性)

    题目大意:给出一系列单词,当某个单词的首字母和前一个单词的尾字母相同,则这两个单词能链接起来.给出一系列单词,问是否能够连起来. 题目分析:以单词的首尾字母为点,单词为边建立有向图,便是判断图中是否存 ...

  2. Uva 10129 - Play on Words 单词接龙 欧拉道路应用

    跟Uva 10054很像,不过这题的单词是不能反向的,所以是有向图,判断欧拉道路. 关于欧拉道路(from Titanium大神): 判断有向图是否有欧拉路 1.判断有向图的基图(即有向图转化为无向图 ...

  3. UVa 10129 Play On Words【欧拉道路 并查集 】

    题意:给出n个单词,问这n个单词能否首尾接龙,即能否构成欧拉道路 按照紫书上的思路:用并查集来做,取每一个单词的第一个字母,和最后一个字母进行并查集的操作 但这道题目是欧拉道路(下面摘自http:// ...

  4. Nyoj42 一笔画问题 (欧拉道路)

    http://acm.nyist.net/JudgeOnline/problem.php?pid=42题目链接 #include <cstdio> #include <cstring ...

  5. 6-14 Inspector s Dilemma uva12118(欧拉道路)

    题意:给出一个国家城市个数n   所需走过道路个数e   每条道路长t   该国家任意两个城市之间都存在唯一道路长t     要求 :找一条最短的路遍历所有所需走过的路 一开始以为是图的匹配  但是好 ...

  6. POJ 2513 Colored Sticks(欧拉道路+字典树+并查集)

    http://poj.org/problem?id=2513 题意: 给定一些木棒,木棒两端都涂上颜色,求是否能将木棒首尾相接,连成一条直线,要求不同木棒相接的一边必须是相同颜色的. 思路: 题目很明 ...

  7. UVA 10129 Play on Words(欧拉道路)

    题意:给你n个字符串,问你是否可以出现一条链,保证链中每个字符串的第一个元素与上一个字符串的最后一个元素相同,注意可能重复出现同一个字符串 题解:以每一个字符串第一个元素指向最后一个元素形成一个有向图 ...

  8. 【UVa】12118 Inspector's Dilemma(欧拉道路)

    题目 题目     分析 很巧秒的一道题目,对着绿书瞎yy一会. 联一下必须要走的几条边,然后会形成几个联通分量,统计里面度数为奇数的点,最后再减去2再除以2.这样不断相加的和加上e再乘以t就是答案, ...

  9. UVA 10441 - Catenyms(欧拉道路)

    UVA 10441 - Catenyms 题目链接 题意:给定一些单词,求拼接起来,字典序最小的,注意这里的字典序为一个个单词比过去,并非一个个字母 思路:欧拉回路.利用并查集判联通,然后欧拉道路判定 ...

随机推荐

  1. javascript之表格节点操作

    <html> <div class='add'>             名字: <input type="" name=""&g ...

  2. 容器之vector

    #include <iostream> #include <vector> #include <string.h> #include <algorithm&g ...

  3. sprintf系列函数

    1 简介和功能 字符串格式化命令,主要功能是把格式化的数据写入某个字符串中.sprintf 是个变参函数. 把格式化的数据写入某个字符串缓冲区. 2 函数原型 int sprintf( char *b ...

  4. bzoj 3172: [Tjoi2013]单词【AC自动机】

    一眼AC自动机,就是先把串建一个自动机,标记每个串在自动机上的位置,然后加上间隔符连成一个串在自动机上跑,每跑到一个点就说明这个串以及它到root的所有点表示的串都要被更新一次 先在点上打上标记,最后 ...

  5. .NET Core 跨平台物联网开发:连接阿里云IOT(一)

    系列教程目录 (一) 连接阿里云IOT (二) 设置委托事件 (三) 上报属性 (四)  SDK文档 属性.方法.委托.类 http://pan.whuanle.cn/index.php?dir=up ...

  6. ES6之箭头函数深入理解

    相对于普通函数的区别 新的书写方式 this 的改变 不能当构造函数 没有 prototype 属性 没有 arguments 对象 新的书写方式 书写方式很简单!直接看下图, 常规方式写一个函数 c ...

  7. NowCoder数列

    题目:https://www.nowcoder.com/questionTerminal/0984adf1f55a4ba18dade28f1ab15003 #include <iostream& ...

  8. HDU - 6058 Kanade's sum

    Bryce1010模板 http://acm.hdu.edu.cn/showproblem.php?pid=6058 /* 思路是:找出每个x为第k大的区间个数有多少 用pos[i]保存当前x的位置, ...

  9. 洛谷P2502[HAOI2006]旅行

    题目: Z小镇是一个景色宜人的地方,吸引来自各地的观光客来此旅游观光.Z小镇附近共有N个景点(编号为1,2,3,-,N),这些景点被M条道路连接着,所有道路都是双向的,两个景点之间可能有多条道路.也许 ...

  10. Ubuntu 安装 node

    ubuntu安装node和npm的命令行命令: sudo apt install nodejs-legacy sudo apt install npm 最新版本安装方法 1.安装npm sudo ap ...