Hdu 1829 A Bug's Life

Problem地址:http://acm.hdu.edu.cn/showproblem.php?pid=1829

 

看完这题,我想到了用并查集。

我用gender[]表示相应编号的小虫的性别--boy / girl

对每只输入的小虫预设性别

如输入 1 2

         3 4 ( 图中B代表boy,G代表girl )

    

继续输入 1 3时,会发现1 3性别相同,但此时还不能判断错误,因为如果将右边这棵树的所有虫子性别更改后及又可满足条件

然后将两树合并

之后怎么判断题中推论是否正确呢?

可以这样:当输入的数据在同一棵树,但两只小虫性别却相同,即可判断错误,如继续输入2 3时。否则一直认为题中推论一直是正确的。

 

因为输入数据很多,可能会有重复输入,所以有必要采取点措施避免重复输入带来的影响。

#include <iostream>

#include <cstring>

#include <cstdio>



using namespace std;



const int boy = 1;

const int girl = -1;



const int maxn = 2000 + 50;

int gender[maxn];

int used[maxn];

bool vis[maxn][maxn];



inline void change ( int &a, int &b )  //交换a,b值,但这可能或许是多此一举

{

    if( a > b )

    {

        a = a+b;

        b = a-b;

        a = a-b;

    }

}



int find( int n )

{

    if( n!=used[n] )

        used[n] = find( used[n] );

    return used[n];

}



void repair( int N, int tar )    //修改一棵树上所有小虫的性别

{

    int i;

    for( i=1;i<=N;i++ )

        if( used[i]==tar )

            gender[i] = - gender[i];

}



int main()

{

    int T;

    int N, M;

    int i, j;

    bool assum; //判断推论是否正确

    int t1, t2;

    int x, y;

    int c=0;

    cin>>T;

    while( T-- )

    {

        scanf( "%d%d", &N, &M );

        memset(vis,false,sizeof(vis));

        memset(gender,0,sizeof(gender));

        for( i=1;i<=N;i++ )

            used[i] = i;   

        assum=true;   //初始化

        for( i=0;i<M;i++ )

        {

            if( assum )

            {

                scanf( "%d%d", &t1, &t2 );

                if( vis[t1][t2] )  //判断是否为重复输入

                    continue;

                change( t1,t2 );

                if( !gender[t1] && !gender[t2] )

                {

                    gender[t1] = boy;

                    gender[t2] = girl;

                    used[t2] = t1;

                }

                else if( !gender[t2] && gender[t1] )

                {

                    x=find(t1);

                    gender[t2] = -gender[t1];

                    change( x, t2 );

                    used[t2] = x;

                }

                else if( !gender[t1] && gender[t2] )

                {

                    x=find(t2);

                    gender[t1] = -gender[t2];

                    change( x, t1 );

                    used[t1] = x;

                }

                else if( gender[t1] && gender[t2] )

                {

                    x = find(t1);

                    y = find(t2);

                    if( x==y && gender[t1]==gender[t2] )

                        assum = false;

                    else if( x!=y && gender[t1]!=gender[t2] )

                    {

                        change(x,y);

                        used[y] = x;

                    }

                    else if( x!=y && gender[t1]==gender[t2] )

                    {

                        change(x,y);

                        repair(N,x);

                        used[y] = x;

                    }

                }

                vis[t1][t2] = vis[t2][t1] = true; //标记输入

            }

            else  //已经有反例说明题中推论错误,就不必继续判断了

                scanf( "%d%d", &t1, &t2 );

        }



        c++;

        printf("Scenario #%d:\n",c);

        if( assum )

            printf("No suspicious bugs found!\n\n");

        else

            printf("Suspicious bugs found!\n\n");

    }

    return 0;

}

 

你可能感兴趣的:(life)