HDU——1272 小希的迷宫(并查集模板题)
程序员文章站
2022-03-15 19:18:20
...
原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=1272
输入样例
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
输出样例
Yes
Yes
No
题意:给你一些关于迷宫的数据,判断是否任意两个房间有且仅有一条路径可以相通(除非走了回头路)。
解题思路:妥妥的一道并查集题目,因为并查集就是将一些点并到一起,即连在一起,若我此时再输入一道数据且这道数据已经连在一起了,那么自然会形成环,使得两个点之间有两条路,说得通一点,这道题就是判断有没有环和有没有把所有的点连在一起,即点集合只有一个。
当然还有其它更简单的水题AC法。(可以过但不推荐,题中数据没有给的很刁钻)
我们来说一下怎么水过去,由于样例给的边不会有重复的,所以我们不会形成环还要是强连通图的条件就是边数+1=点数。利用这个再特判一下点全为0的条件。即可水过该题。
并查集AC代码:
/*
*邮箱:aaa@qq.com
*blog:https://me.csdn.net/hzf0701
*注:文章若有任何问题请私信我或评论区留言,谢谢支持。
*
*/
#include<bits/stdc++.h> //POJ不支持
#define rep(i,a,n) for (int i=a;i<=n;i++)//i为循环变量,a为初始值,n为界限值,递增
#define per(i,a,n) for (int i=a;i>=n;i--)//i为循环变量, a为初始值,n为界限值,递减。
#define pb push_back
#define IOS ios::sync_with_stdio(false);cin.tie(0); cout.tie(0)
#define fi first
#define se second
#define mp make_pair
using namespace std;
const int inf = 0x3f3f3f3f;//无穷大
const int maxn = 1e5+2;//最大值。
typedef long long ll;
typedef long double ld;
typedef pair<ll, ll> pll;
typedef pair<int, int> pii;
//*******************************分割线,以上为自定义代码模板***************************************//
int father[maxn];//存储所连结点。
int Find(int x){
int r=x;
while(father[r]!=r)
r=father[r];
//找到根节点。
//回溯降低深度。
int i=x,j;
while(father[i]!=r){
j=father[i];
father[i]=r;
i=j;
}
return r;
}
void Merge(int x,int y){
//合并x和y。
int fx=Find(x),fy=Find(y);
if(fx!=fy)
father[fx]=fy;
}
int main(){
//freopen("in.txt", "r", stdin);//提交的时候要注释掉
IOS;
int u,v;
while(1){
bool flag=false;
memset(father,0,sizeof(father));//由于顶点编号是随机的,所以我们必需对顶点初始化后为0,再对输入数据进行编号处理。
while(cin>>u>>v&&(u+v)){
if(u==-1&&v==-1)return 0;
if(father[u]==0)father[u]=u;
if(father[v]==0)father[v]=v;
if(Find(u)==Find(v)){
flag=true;//如果它们对应的终点相同,意味着它们已经连通,此时连接这两个点自然存在环。
}
else if(!flag)//这里判断flag是因为如果flag为true就已经得到了答案,无须浪费时间。
Merge(u,v);//连接u,v
}
int sum=0;//判断有多少个集合。
if(flag)
cout<<"No"<<endl;
else{
rep(i,1,maxn){
if(father[i]==i)sum++;
}
if(sum>1)
cout<<"No"<<endl;
//说明在两个集合里。
else
cout<<"Yes"<<endl;
}
}
return 0;
}
水题AC代码
/*
*邮箱:aaa@qq.com
*blog:https://me.csdn.net/hzf0701
*注:文章若有任何问题请私信我或评论区留言,谢谢支持。
*
*/
#include<bits/stdc++.h> //POJ不支持
#define rep(i,a,n) for (int i=a;i<=n;i++)//i为循环变量,a为初始值,n为界限值,递增
#define per(i,a,n) for (int i=a;i>=n;i--)//i为循环变量, a为初始值,n为界限值,递减。
#define pb push_back
#define IOS ios::sync_with_stdio(false);cin.tie(0); cout.tie(0)
#define fi first
#define se second
#define mp make_pair
using namespace std;
const int inf = 0x3f3f3f3f;//无穷大
const int maxn = 1e5+2;//最大值。
typedef long long ll;
typedef long double ld;
typedef pair<ll, ll> pll;
typedef pair<int, int> pii;
//*******************************分割线,以上为自定义代码模板***************************************//
bool vis[maxn];
int cnt1,cnt2;
int main(){
//freopen("in.txt", "r", stdin);//提交的时候要注释掉
IOS;
int u,v;
while(1){
cnt1=0;cnt2=0;
memset(vis,false,sizeof(vis));
while(cin>>u>>v&&(u+v)){
if(u==-1&&v==-1)return 0;
vis[u]=vis[v]=true;
cnt1++;
}
rep(i,1,1e5)
if(vis[i])cnt2++;
if(cnt2==0||cnt2==cnt1+1)
cout<<"Yes"<<endl;
else
cout<<"No"<<endl;
}
return 0;
}
上一篇: java多态