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;
}

 

posted @ 2014-09-22 22:15  Emerald  阅读(203)  评论(0编辑  收藏  举报