1. 程式人生 > >HDU 1272 小希的迷宮 基礎並查集★

HDU 1272 小希的迷宮 基礎並查集★

並查集的基礎題,輸入時判斷一下兩個點的根節點是否已經聯通,如果已經聯通那麼說明迷宮不符合要求,需要注意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; }