1. 程式人生 > >POJ611 The Suspects並查集+優先佇列

POJ611 The Suspects並查集+優先佇列


題目大意: 非典來襲 n 個人 m 個團隊, n個人的編號為0 --- n-1 其中已知 0 被懷疑攜帶非典病毒,如果一個隊伍中有一個人是

被懷疑攜帶有此病毒,那麼這一個團隊中的所有人都被i懷疑攜帶有非典病毒。

輸入格式:

第一行 n m 代表 n個人 m個團隊

接下來的m行 每一行代表一個團隊  每一行的第一個數為團隊人數  後面接上 此團隊的人員編號

直到輸入中 n m全為0  方才結束。

輸出:所有可能攜帶次病毒的人員的數量。

解析:很明顯 用並查集  另外 考慮一下極端情況 

如果輸入的資料為:

30000 1

3 0 29999 15000

0 0

那麼 真是哦存在的只有三個人 0 15000 29999 如果i迴圈從0一個一個列舉 則不太好 

好一點的方法就是用優先佇列 將這三個數儲存起來  用的時候 一個一個彈出 即可。

程式碼C:

# include <stdio.h>
# define N 30001
void insert(int Tree[],int X);//向堆中插入值 S[WEI]
int Delmin(int Tree[]);       //刪除堆頭-並返回堆頭
int find(int x);
void Link(int x,int y);
int tree[N+1];  //堆
int p[N],Q[N];
int main()
{
    int n,m,a,b,c,i,j,k;
  //  freopen("AAA.txt","r",stdin);
    while(scanf("%d%d",&n,&m)&&(n||m))
    {
        while(m--)
        {
            scanf("%d%d",&a,&c);
            c++;
            Link(c,c);
            while(--a>0){
                scanf("%d",&b);
                if(find(++b)!=c)Link(b,c);
            }
        }
        n=0;
        while(tree[0])Q[n++]=Delmin(tree);
            for(i=k=0,c=find(1); i<n; i++)
                if(p[Q[i]])
                {
                    if(find(Q[i])==c)tree[++k]=Q[i];
                    else p[Q[i]]=0;
                }
        if(k)printf("%d\n",k);
        else printf("1\n");
        while(k)p[tree[k--]]=0;
    }
    return 0;
}
void insert(int Tree[],int X)//向最小堆中插入X
{
    int par,i=++Tree[0];            //插入X 後 Tree[0]+1
    while(i>1)                      //直到i不是根節點
    {
        par=(i>>1);                 //父節點為par
        if(Tree[par]<=X) break;     //將<=改為>=即改為最大堆了
        Tree[i]=Tree[par];          //否則調整堆 即位置上移
        i=par;
    }
    Tree[i]=X;                      //插入新節點
}
int Delmin(int Tree[])
{
    int i=1,L=2,root=Tree[1],X=Tree[Tree[0]--];
    while(L<=Tree[0])
    {
        L+=L<Tree[0]&&Tree[L+1]<Tree[L];
        if(Tree[L]>=X) break;
        Tree[i]=Tree[L];
        i=L;
        L=i<<1;
    }
    Tree[i]=X;
    return  root;
}
int find(int x)
{
    int y=x;
    if(p[x])while(x!=p[x]) x=p[x];
    else insert(tree,x);
    return p[y]=x;
}
void Link(int x,int y)
{
    p[find(x)]=find(y);
}