uva10129
2016-04-10 10:04
381 查看
题目描述:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=19492
/*1:通常想法是将每个单词看成一个节点,但如果单词的尾部与另外一个单词的首部相同,就能架起一座“桥”,但这样以来,数组就开太大了 2:将每个单词的首尾两个字母看成节点,此时单词就是一座桥。这样就可以根据欧拉道路的出入度来判断 3:注意题中判断欧拉道路的起点以及终点的技巧*/ #include <cstdio> #include <cstring> #include <iostream> #include <string> using namespace std; const int maxc = 1000 + 5; int n, in[30], out[30], graph[30][30], start, visit[30]; //从start这个点开始dfs void dfs(int u) { visit[u] = 1; for(int v = 0; v < 26; v++) { if(graph[u][v] > 0) { //因为节点可以重复,所以不能在条件里加上 && !visit[v] graph[u][v]--; graph[v][u]--; dfs(v); } } } bool isConnected() { memset(visit, 0, sizeof(visit)); dfs(start); for(int i = 0; i < 26; i++) if(in[i] + out[i]) //出入度为0的字母没有出现过,此时不计 if(!visit[i]) return false; return true; } bool solve() { if(!isConnected()) return false; int theBegin = 0, theEnd = 0; for(int u = 0; u < 26; u++) { if(in[u] != out[u]) { if(!theBegin && out[u] - in[u] == 1) theBegin = 1; else if(!theEnd && in[u] - out[u] == 1) theEnd = 1; else return false; } } return true; } int main() { int kase; scanf("%d", &kase); while(kase--) { scanf("%d", &n); //初始化 memset(in, 0, sizeof(in)); memset(out, 0, sizeof(out)); memset(graph, 0, sizeof(graph)); //输入同时确定出度以及入度 string str; for(int i = 0; i < n; i++) { cin >> str; int u = str[0] - 'a'; int v = str[str.length() - 1] - 'a'; out[u]++; in[v]++; graph[u][v]++; graph[v][u]++;//注意虽然是有向图,但这行代码这样写的目地是为了dfs能够顺利遍历整张图,不然有些点访问不到 start = u; } if(solve()) printf("Ordering is possible.\n"); else printf("The door cannot be opened.\n"); } }
相关文章推荐
- C++数据类型范围
- 机房重构——组合查询
- 线程的同步及线程池
- 61. Rotate List
- IF函数
- 实现由双亲节点存储的树转化为二叉树的遍历算法实现
- Derived 派生类
- 千万不要在Android的Application对象中缓存数据!
- 嵌入式开发中相关开发环境搭建
- BroadcastReceiver
- Miller_Rabin质数测试
- [C#] 整型溢出与浮点数精度 - C#袖珍参考手册
- [leetcode] 341. Flatten Nested List Iterator 解题报告
- 界面组件:表单输入
- Corosync + Pacemaker 搭建高可用MariaDB服务
- UI-定时器与动画使用总结
- C语言学习017:malloc和free
- Android进阶-MVP
- String类中split方法的使用
- 浮点数的存储形式