uva 10129 Play On Words(并查集法和DFS法)
2015-08-11 09:15
351 查看
原题链接:
https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1070
考查有向图的欧拉路。
判断条件:
1.忽略边的方向后图连通。
2.出度==入度 +(一个 顶点出度+1==入度,一个顶点 入度+1==出度) 这两个顶点可有可无
判断图连通方法:
1.并查集法
说白了就是建一个与结点数相等的数组,里面存对应结点的上一个结点。因此,可以通过该数组找到根节点。
通过判断根节点是否相同来判断图是否连通。
2.DFS法
DFS一遍后,如果所有节点遍历到,则图连通;否则,不连通。
a.可直接利用G图判断是否有没遍历到的边。
b.可建一个辅助数组vis,记录该点是否遍历到。
详见代码:
并查集法:
DFS法:
注释部分为用辅助数组vis的方法。
https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1070
考查有向图的欧拉路。
判断条件:
1.忽略边的方向后图连通。
2.出度==入度 +(一个 顶点出度+1==入度,一个顶点 入度+1==出度) 这两个顶点可有可无
判断图连通方法:
1.并查集法
说白了就是建一个与结点数相等的数组,里面存对应结点的上一个结点。因此,可以通过该数组找到根节点。
通过判断根节点是否相同来判断图是否连通。
2.DFS法
DFS一遍后,如果所有节点遍历到,则图连通;否则,不连通。
a.可直接利用G图判断是否有没遍历到的边。
b.可建一个辅助数组vis,记录该点是否遍历到。
详见代码:
并查集法:
#include<iostream> #include<string> #include<cstring> using namespace std; int indegree[30], outdegree[30],pre[30];//分别记录:入度、出度、该结点的前一个结点 int find(int x) { int p = x; while (pre[p] != p) p = pre[p]; //下面这个循环可不写。 并查集的路径压缩 int i = x, j; while (pre[i] != p) { j = pre[i]; pre[i] = p; i = j; } return p; } int main() { int T; cin >> T; while (T--) { string str; int n,begin,end,root; memset(indegree, 0, sizeof(indegree)); memset(outdegree, 0, sizeof(outdegree)); for (int i = 0; i < 30; i++) //勿忘初始化 pre[i] = i; cin >> n; for (int i = 0; i < n; i++) { cin >> str; begin = str[0] - 'a'; end = str[str.length() - 1] - 'a'; outdegree[begin]++; indegree[end]++; pre[find(begin)] = find(end); //将根结点相连接,更新根结点 root = find(end); //root记录根结点,不断更新,直到最根本的那个结点 } bool p = false; int sumin = 0,sumout=0; for (int i = 0; i < 26; i++) { if (indegree[i] || outdegree[i]) { if (find(i) != root) //如果该结点的根节点与root不一样,说明图不连通 p = true; if (indegree[i] == outdegree[i]) continue; if (indegree[i] + 1 == outdegree[i]) sumout++; else if (indegree[i] == outdegree[i] + 1) sumin++; else p = true; //属 |入度 - 出度|>=2 的情况 if (p || sumin >= 2 || sumout >= 2) break; } } if (p || sumin >= 2 || sumout >= 2) cout << "The door cannot be opened." << endl; else cout << "Ordering is possible." << endl; } return 0; }
DFS法:
注释部分为用辅助数组vis的方法。
#include<iostream> #include<string> #include<cstring> using namespace std; int G[27][27], indegree[30], outdegree[30]; //bool vis[30]; void DFS(int u) { //vis[u] = true; //标记遍历过该点 for (int v = 0; v < 26; v++) { if (G[u][v]) { G[u][v]--; G[v][u]--; //别忘是判断无向图的连通性 DFS(v); } } } int main() { int T; cin >> T; while (T--) { string str; int n; int begin, end; memset(indegree, 0, sizeof(indegree)); memset(outdegree, 0, sizeof(outdegree)); memset(G, 0, sizeof(G)); //memset(vis, 0, sizeof(vis)); cin >> n; for (int i = 0; i < n; i++) { cin >> str; begin = str[0] - 'a'; end = str[str.length() - 1] - 'a'; outdegree[end]++; indegree[begin]++; G[begin][end]++; G[end][begin]++; } DFS(0); int sumin = 0, sumout = 0; bool boss = false; for (int i = 0; i < 26; i++) { for (int j = 0; j < 26;j++) //判断是否有没遍历到的边 if (G[i][j]) { boss = true; break; } if (indegree[i] || outdegree[i]) { /*if (vis[i] == false) //判断是否有没遍历到的点 { boss = true; break; }*/ if (indegree[i] == outdegree[i]) continue; if (indegree[i] + 1 == outdegree[i]) sumout++; else if (indegree[i] == outdegree[i] + 1) sumin++; else //属 |入度 - 出度|>=2 的情况 { boss = true; break; } if (boss || sumin >= 2 || sumout >= 2) break; } } if (boss || sumin >= 2 || sumout >= 2) cout << "The door cannot be opened." << endl; else cout << "Ordering is possible." << endl; } return 0; }
相关文章推荐
- 计蒜客 难题题库 220 线段的总长
- Struts2 Hello World 实例
- mov eax, dword ptr [esi]指令区别
- 结构的具体说明sublime text 2/3的Golang开发环境
- PHP5.3安装Zend Guard Loader代替Zend Optimizer
- 月卡逻辑
- swt byte[] 与 Image的转换
- ecshop的订单状态都是在ecs_order_info表中的字段里
- Win10系统KB3081424累积补丁更新后出现反复重启的BUG
- linux 安装php
- 计蒜客 难题题库 219 最大质因数
- **Jquery-之jqGrid表格插件学习(一)**
- IOS代码添加控件,控件移动,放大,缩小,旋转
- 高性能JavaScript 重排与重绘
- Android利用Intent与其他应用交互
- 【坑】html5中使用canvas绘制两个strokeRect之间忘了用beginPath()
- maven中使用不同配置文件打包
- ExtraCHM 1.5破解版和破解教程:
- Failed to load JavaHL Library解决方法
- 使用nginx sticky实现基于cookie的负载均衡