码迷,mamicode.com
首页 > 其他好文 > 详细

hdu A Bug's Life

时间:2015-07-17 18:04:00      阅读:92      评论:0      收藏:0      [点我收藏+]

标签:

 题目意思:给定一系列数对,例如a和b,表示a和b不是同一种性别,然后不断的给出这样的数对,问有没有性别不对的情况。

例如给定:
1    2
3    4
1    3
那这里就是说1和2不是同种性别,3和4也不是同种性别,1和3不是同种性别,那这样就说明1和3是同一种性别,2和4是同一种性别,所以没有任何歧义,这时候输出No suspicious bugs found!。
但是例如
1 2
2 3
1 3
1和2不同性别,2和3不同性别,那么1和3同一性别的,但是第三组数对又表明1和3不同性别,所以这里就出现了3或者1的性别出现了歧义,也就是说条件矛盾,这时候输出Suspicious bugs found!.

这道题一开始的想法是构一张图,判断这个无向图中是否存在环。如果存在环,则说明存在同性的,否则不存在。这里用到了一个公式:无向图中,如果  边数+连通分量数>顶点数,则存在环,否则不存在。

  一开始没有对bfs做优化处理,所以超内存了。做了处理之后wa掉了。。。稍微想想就知道是边的数目问题,因为这个是当做无向图处理的,所以在输入时,同一条边可能输入了两次,例如输入1 3和3 1应该是同一条边。所以还要做额外的处理。

  做了处理之后还是wa。参考网上的代码,没有一个是思路和我一样的。当时确实没有想到是分组并查集。这里先附上错误的代码,如果有人知道错误在哪望相告。

技术分享
#include"iostream"
#include"stdio.h"
#include"algorithm"
#include"cmath"
#include"string.h"
#include"string"
#include"queue"
using namespace std;
bool flag;
int num_e,num_v,num_p,nume;
bool visited[2005];
bool judge[2005][2005];
struct node
{
    int data;
    node *next;
};
struct Head
{
   node *first;
};
Head head[2005];


void init()
{
    for(int i=1;i<=num_v;i++)
    {
        head[i].first=NULL;
    }
}


void creat(int fa,int son)//利用邻接表构图
{
    node *temp=new node;
    temp->data=son;
    temp->next=head[fa].first;
    head[fa].first=temp;
}


void bfs(int i)//利用bfs把同一个连通分量中的点标记起来,从而判断连通分量的个数
{
    queue<int>q;
    while(!q.empty()) q.pop();
    q.push(i);
    int cur;
    node *temp=new node;
    while(!q.empty())
    {
        cur=q.front();
        q.pop();
        temp=head[cur].first;
        while(temp!=NULL)
        {
            if(!visited[temp->data])
            {
                visited[temp->data]=true;
                q.push(temp->data);
            }
            temp=temp->next;
        }
    }
}


int main()
{
    int case_count,case_num;
    int bug1,bug2;
    scanf("%d",&case_num);
    for(case_count=1;case_count<=case_num;case_count++)
    {
        num_p=0;
        nume=0;
        memset(visited,false,sizeof(visited));//用于标记点是否被访问过
        memset(judge,false,sizeof(judge));//用于标记边是否重复
        flag=false;
        scanf("%d%d",&num_v,&num_e);
        init();
        for(int i=0;i<num_e;i++)
        {
            scanf("%d%d",&bug1,&bug2);
            if(!judge[bug1][bug2])
            {
                    judge[bug1][bug2]=judge[bug2][bug1]=true;
                    creat(bug1,bug2);
            }
            else
                nume++;
        }
        num_e-=nume;//实际边的数目
       cout<<"Scenario #"<<case_count<<":"<<endl;
        for(int i=1;i<=num_v;i++)
        {
              if(!visited[i])
            {
                visited[i]=true;
                num_p++;
                bfs(i);
            }
        }
        cout<<num_p<<" "<<num_e<<" "<<num_v<<endl;
        if(num_p+num_e>num_v) flag=true;//判断原图中是否存在环
        if(flag)
            cout<<"Suspicious bugs found!"<<endl;
        else
            cout<<"No suspicious bugs found!"<<endl;
        cout<<endl;
    }
    return 0;
}
View Code

下面是我用分组并查集写的代码,参考了一下网上的思路:

1.开两个并查集,然后合并的时候要合并两次,这样在合并之前判断是否冲突,如果不冲突就进行合并,否则不需要继续合并。
2.开一个并查集,但是要加个偏移向量数组,来记录每个节点距离根节点的距离,但这里最好取一下余,因为毕竟只有两个分组。
 

hdu A Bug's Life

标签:

原文地址:http://www.cnblogs.com/acm-jing/p/4655151.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!