HDU 1272 小希的迷宮 基礎並查集★
阿新 • • 發佈:2019-01-10
並查集的基礎題,輸入時判斷一下兩個點的根節點是否已經聯通,如果已經聯通那麼說明迷宮不符合要求,需要注意2點:
1.當直接輸入0 0時這時直接輸出Yes,進行下一次輸入,因為0 0也滿足題目的要求。
2.迷宮必須是聯通的1 2 3 4 0 0這組樣例是錯誤的,因為迷宮兩處被分開.
1的解決辦法很簡單直接判斷就行,2就要記錄一下每個點所在的集合的點的數目,首先點的總數應該記下,這個很好判斷,開一個數組全部賦值為0,當兩個點輸入時判斷一下兩個點是否出現過,即a[x],a[y]是否等於0,等於0則點的總數加一,a[x],a[y]也加一。當判斷髮現兩個點的根節點不聯通時,合併根節點時也合併兩個集合的點的數目,每個集合剛開始時的數目是1,合併集合時把數目也合併起來,我的程式碼是合併給大的那個根節點。程式碼如下:
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=100050;
int pre[maxn],num[maxn],a[maxn];
void creat()
{
for(int i=0;i<=maxn;i++)
{
pre[i]=i;
num[i]=1;
}
}
int findroot(int root)
{
int son=root,tmp;
while(root!=pre[root])
root=pre[root];
while(son!=pre[son])
{
tmp=pre[son];
pre[son]=root;
son=tmp;
}
return root;
}
int main()
{
int n,m,x,y,flag=0;
int sum=0;
while(scanf("%d %d",&n,&m)==2&&n!=-1&&m!=-1)
{
if (!n&&!m)
{
puts("Yes");
continue;
}
int nn=n;
flag=0;
sum=0;
memset(a,0,sizeof(a));
if(a[n]==0)
{
sum++;
a[n]++;
}
if(a[m]==0)
{
sum++;
a[m]++;
}
creat();
int root1=findroot(n);
int root2=findroot(m);
if(n<m)
swap(n,m);
pre[m]=n;
num[n]+=num[m];
while(scanf("%d %d",&n,&m)==2&&n&&m)
{
if(a[n]==0)
{
sum++;
a[n]++;
}
if(a[m]==0)
{
sum++;
a[m]++;
}
root1=findroot(n);
root2=findroot(m);
if(root1==root2)
{
flag=1;
}
if(root1<root2)
swap(root1,root2);
pre[root2]=root1;
num[root1]+=num[root2];
}
int tmp=findroot(nn);
//printf("%d %d %d %d\n",sum,num[tmp],tmp,nn);
if(flag==1||num[tmp]!=sum)
puts("No");
else
puts("Yes");
}
return 0;
}