0
点赞
收藏
分享

微信扫一扫

HDU——1272 小希的迷宫(并查集模板题)

原题链接:​​http://acm.hdu.edu.cn/showproblem.php?pid=1272​​

HDU——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代码

/*

*
*/
#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代码

/*

*
*/
#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;
}


举报

相关推荐

0 条评论