[kuangbin帶你飛]專題五 並查集(hdu1272 判環)

M - 小希的迷宮HDU - 1272

在這裏插入圖片描述
在這裏插入圖片描述

題意:

輸入很多條邊,要你判斷這些邊連成的迷宮不存在環。

思路:

  1. 自環的情況,當兩個點如果他們的祖先相同,此時再將他們並在一起,會導致內環。
  2. 特判:輸入0 0 時要輸出yes。

AC( 3. 我考場時的代碼):

我當時想沒有環,那麼 邊數+1= 點數。

#include <iostream>
#include <cstdio>
#include <cstring>
#define For(i,x,y) for(register int i=(x); i<=(y); i++)
#define mst(x,a) memset(x,a,sizeof(x))
using namespace std;
const int maxn=1e5+10;
int max_num=0,flag;
int f[maxn],in[maxn];
int find(int x)
{
    if(f[x]==-1)return x;
    return f[x]=find(f[x]);
}
void merge(int u, int v)
{
    int uf=find(u);
    int vf=find(v);
    max_num=max(u,max(max_num,v));
    if(uf!=vf)f[uf]=vf;
    else flag=0;
}
int main()
{
    int n,m,ed=0;
    while(~scanf("%d%d", &n,&m))
    {
        if(n==0)
        {
            printf("Yes\n");//特判
            continue;
        }
        ed=max_num=0;
        flag=1;
        if(n==m&&n==-1)break;
        mst(f,-1);
        mst(in,0);
        merge(n,m);
        ed++;
        while(scanf("%d%d",&n,&m)&&(n|m))
        {
            merge(n,m);
            ed++;
        }
        For(i,1,max_num)in[find(i)]++;
        if(in[find(max_num)]==ed+1&&flag)printf("Yes\n");
        else printf("No\n");
    }
    return 0;
}

AC(4. 考慮是否只有一個集合)

#include <iostream>
#include <cstdio>
#include <cstring>
#define For(i,x,y) for(register int i=(x); i<=(y); i++)
#define mst(x,a) memset(x,a,sizeof(x))
using namespace std;
const int maxn=1e5+10;
int max_num=0,flag;
int f[maxn],vis[maxn];
int find(int x)
{
    if(f[x]==-1)return x;
    return f[x]=find(f[x]);
}
void merge(int u, int v)
{
    int uf=find(u);
    int vf=find(v);
   vis[u]=vis[v]=1;
    max_num=max(u,max(max_num,v));
    if(uf!=vf)f[uf]=vf;
    else flag=0;
}
int main()
{
    int n,m,cnt=0;
    while(~scanf("%d%d", &n,&m))
    {
        if(n==0)
        {
            printf("Yes\n");
            continue;
        }
        cnt=max_num=0;
        flag=1;
        if(n==m&&n==-1)break;
        mst(f,-1);
        mst(vis,0);
        merge(n,m);
        while(scanf("%d%d",&n,&m)&&(n|m))
        {
            merge(n,m);
        }
        For(i,1,max_num)
        {
            if(vis[i]&&find(i)==i)cnt++;
        }
        if(cnt==1&&flag)printf("Yes\n");
        else printf("No\n");
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章