HDOJ 1272 小希的迷宫 (并查集实现 及 Tarjan实现)
2017-08-02 09:59
465 查看
小希的迷宫
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768K (Java/Others)
Total Submission(s): 53159 Accepted Submission(s): 16627
Problem Description
上次Gardon的迷宫城堡小希玩了很久(见Problem B),现在她也想设计一个迷宫让Gardon来走。但是她设计迷宫的思路不一样,首先她认为所有的通道都应该是双向连通的,就是说如果有一个通道连通了房间A和B,那么既可以通过它从房间A走到房间B,也可以通过它从房间B走到房间A,为了提高难度,小希希望任意两个房间有且仅有一条路径可以相通(除非走了回头路)。小希现在把她的设计图给你,让你帮忙判断她的设计图是否符合她的设计思路。比如下面的例子,前两个是符合条件的,但是最后一个却有两种方法从5到达8。
Input
输入包含多组数据,每组数据是一个以0 0结尾的整数对列表,表示了一条通道连接的两个房间的编号。房间的编号至少为1,且不超过100000。每两组数据之间有一个空行。
整个文件以两个-1结尾。
Output
对于输入的每一组数据,输出仅包括一行。如果该迷宫符合小希的思路,那么输出"Yes",否则输出"No"。
Sample Input
6 8 5 3 5 2 6 4
5 6 0 0
8 1 7 3 6 2 8 9 7 5
7 4 7 8 7 6 0 0
3 8 6 8 6 4
5 3 5 6 5 2 0 0
-1 -1
Sample Output
Yes
Yes
No
Author
Gardon
Source
HDU 2006-4 Programming Contest
Recommend
lxj | We have carefully selected several similar problems for you: 1213 1856 1325 1198 1875
题目要求: 连通且无环。
坑点: 只有0 0时要输出 Yes 。
解法一:Tarjan算法
一开始没想到并查集,刚学了Tarjan可以判环,就试了一试,因为有的结点push_bcak了很多次,差点MLE,(⊙﹏⊙) 。
#include <iostream> #include <sstream> #include <cstring> #include <cstdio> #include <cctype> #include <cmath> #include <map> #include <set> #include <list> #include <queue> #include <deque> #include <stack> #include <vector> #include <algorithm> #define inf 0x3f3f3f3f #define PI 3.14159265358979323 #define SCD(a) scanf("%d",&a) #define SCDD(a,b) scanf("%d%d",&a,&b) #define SCF(a) scanf("%lf",&a) #define PTD(a) printf("%d\n",a) #define PTS(a) printf("%s\n",a) #define MST(a) memset(a, 0, sizeof(a)) using namespace std; // HDOJ 1272 const int L = 100001; int n, m; vector<int > v[L]; //邻接链表 stack<int> s; int cnt; bool instack[L]; int low[L], dfn[L], maxnum, index; int point, dui; void init() //初始化 { int i; for(i=1;i<L;i++){ v[i].clear(); instack[i] = false; dfn[i] = 0; } while(!s.empty()) s.pop(); cnt = 0; //强连通分量 maxnum = 0; //最大下标 index = 1; point = 0; dui = 0; //总共输入点的对数 } void tarjan(int x) //Tarjan模板 { int i, t; instack[x] = true; low[x] = dfn[x] = index++; s.push(x); for(i=0;i<v[x].size();i++){ t = v[x][i]; if(!dfn[t]){ tarjan(t); low[x] = min(low[x], low[t]); }else if(instack[t]){ point ++ ; //在这里统计point数 low[x] = min(low[x], dfn[t]); } } if(low[x] == dfn[x]){ cnt ++ ; //强连通 do{ t = s.top(); s.pop(); instack[t] = false; }while(x != t); } } int main() { int i ,j ,a ,b ,t; while(SCDD(n, m)!=EOF){ if(n == m && m == -1) return 0; if(!n && !m){ PTS("Yes"); continue; } init(); if(m != n){ v .push_back(m); v[m].push_back(n); maxnum = max(n, m); dui ++ ; } while(SCDD(a, b) && (a || b)){ if(a != b){ v[a].push_back(b); v[b].push_back(a); maxnum = max( maxnum, max(a, b)); dui ++ ; } } for(i=1;i<=maxnum;i++){ if(v[i].size() && !dfn[i]){ tarjan(i); } } if(cnt == 1 && point == dui){ PTS("Yes"); }else{ //强连通分量个数不为1说明不连通, point数不等于总对数说明有环 PTS("No"); } /* PTD(cnt); PTD(point); */ } return 0; } /* Sample Input 6 8 5 3 5 2 6 4 5 6 0 0 8 1 7 3 6 2 8 9 7 5 7 4 7 8 7 6 0 0 3 8 6 8 6 4 5 3 5 6 5 2 0 0 -1 -1 Sample Output Yes Yes No */
解法二: 并查集
发现并查集的课件里有这道题,一脸懵逼,于是又回来试了试,果然好很多。╮(╯▽╰)╭ 。
#include <iostream> #include <sstream> #include <cstring> #include <cstdio> #include <cctype> #include <cmath> #include <map> #include <set> #include <list> #include <queue> #include <deque> #include <stack> b56f ; #include <vector> #include <algorithm> #define inf 0x3f3f3f3f #define PI 3.14159265358979323 #define SCD(a) scanf("%d",&a) #define SCDD(a,b) scanf("%d%d",&a,&b) #define SCF(a) scanf("%lf",&a) #define PTD(a) printf("%d\n",a) #define PTS(a) printf("%s\n",a) #define MST(a) memset(a, 0, sizeof(a)) using namespace std; // HDOJ 1272 int f[100001],ans,mount; int fid(int x) //查 { if(f[x] != x) return fid(f[x]); return x; } int main() { int i,j,n,t,num,use[100001],cou; int a,b,x,y; bool esc = false; while(true){ ans = 1; cou = 0; for(i=1;i<=100001;i++){ f[i] = i; use[i] = 0; } t = 0; int ling = 1; // 0 0要Yes while(true){ SCDD(a, b); if(a == b && b == 0) break; if(a == b && b == -1){ return 0; } ling = 0; use[a] = use[b] = 1; if(a == b) continue; x = fid(a); y = fid(b); if(x == y) ans = 0; //有环 if(x > y) swap(x, y); f[x] = y; // 并 } if(ling){ PTS("Yes"); continue; } int muse = 0; for(i = 1; i <= 100000; i++) if(use[i]==1) muse++; for(i = 1;i <= 100000; i++){ if(f[i] != i) cou++; } //cout<<muse<<" "<<cou<<endl; if(ans&&((muse-cou)==1)) //连通图 muse - cou 应该为1, 即集合总数数为一 PTS("Yes"); else PTS("No"); } } /* Sample Input 6 8 5 3 5 2 6 4 5 6 0 0 8 1 7 3 6 2 8 9 7 5 7 4 7 8 7 6 0 0 3 8 6 8 6 4 5 3 5 6 5 2 0 0 -1 -1 Sample Output Yes Yes No */
相关文章推荐
- hdoj1272小希的迷宫(并查集)
- HDOJ 1272 小希的迷宫(并查集)
- HDOJ1272~小希的迷宫~并查集
- HDOJ1272 小希的迷宫(并查集)
- HDOJ 1272 小希的迷宫(基础并查集)
- HDOJ 1272 小希的迷宫(并查集)
- Num 21 : HDOJ: 题目1272 : 小希的迷宫 ( 并查集问题 )
- HDOJ 1272 小希的迷宫(并查集)
- HDOJ 1272 小希的迷宫(并查集的应用)
- HDOJ 1272 小希的迷宫 (并查集)
- hdoj 1272 小希的迷宫【并查集】
- HDOJ---1272 小希的迷宫[并查集]
- HDOJ 1272 小希的迷宫(并查集)
- hdoj 1272 小希的迷宫 【并查集】
- HDOJ 1272 小希的迷宫 (并查集)
- 并查集基础-----HDOJ1272-----小希的迷宫
- HDOJ 1272 小希迷宫 (并查集)
- HDOJ 题目1272 小希的迷宫(并查集)
- [HDOJ]problem_1272【小希的迷宫】并查集
- hdoj--1272--小希的迷宫(并查集)