zoukankan      html  css  js  c++  java
  • hdu A Bug's Life

     题目意思:给定一系列数对,例如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

    看了别人的思路,感觉似乎自己一开始想的就是错的。这题好像没有判断无向图有没有环这么简单。。。但是我也找不出其他的反例。感觉如果存在同性,必然是无向图中存在环。当然,如果无向图中存在环,必然存在同性。

    #include <stdio.h>
    //存储的是其父亲的下表
    int bugs[2010];
    int relation[2010];//1:相同性别 0:不同性别
    //初始化
    void init(int len)
    {
        for(int i = 0;i <= len; i++)
        {
            bugs[i] = i;
            relation[i] = 1;
        }
    }
    //找到根
    int find(int bug)
    {
        if(bugs[bug]==bug)return bug;
        int tem = bugs[bug];
        bugs[bug] = find(bugs[bug]);
        //递归更新域,返回最终的父亲节点,把所有的孩子都更新了
        //注意这里,求当前位置和父亲的关系,记录之前父亲的位置为tem,然后因为是递归,
        //此时的relation[tem]已经在递归中更新过了,也就是孩子和父亲的关系+父亲和爷爷的关系+1然后模2就得到
        //孩子和爷爷的关系,这里用0和1表示,0表示不同性别,1表示相同性别
        relation[bug] = (relation[bug]+relation[tem]+1)%2;
        return bugs[bug];
    }
    
    void union_set(int a,int b,int x,int y)
    {
        //合并,让前边的集合的根指向后边集合的根,成为一个集合
        bugs[x]=y;
        //更新前边集合根和新的集合根之间的关系,
        //注意这里,relation[a]+relation[x]与relation[b]
        //相对于新的父节点必须相差1个等级,因为他们不是gay
        relation[x] = (relation[b]-relation[a])%2;
    }
    
    int main()
    {
        int S;
        int n,inter;
        int bug1,bug2,parent1,parent2;
        bool flag;//false:无同性恋,true:有同性恋
        scanf("%d",&S);
        for(int i=1; i<=S;i++)
        {
            scanf("%d%d",&n,&inter);
            flag = false;
            init(n);//初始化,使其父节点为自己
            for(int j = 1; j <= inter; j++)
            {
                scanf("%d%d",&bug1,&bug2);
                if(flag)continue;
                parent1 = find(bug1);
                parent2 = find(bug2);
                if(parent1==parent2)
                {
                    if(relation[bug1]==relation[bug2])//同性
                    flag = true;
                }
                union_set(bug1,bug2,parent1,parent2);
            }
            if(flag)
            printf("Scenario #%d:
    Suspicious bugs found!
    ",i);
            else
            printf("Scenario #%d:
    No suspicious bugs found!
    ",i);
            printf("
    ");
        }
        return 0;
    }
    View Code
  • 相关阅读:
    angularJs实现级联操作
    FastDFS简单入门小demo
    FastDFS初步认识--上传下载流程介绍
    什么是spu和sku
    centOS7 flask项目布署
    Error: Another program is already listening on a port that one of our HTTP servers is configured to use. Shut this program down first before starting supervisord.
    gunicorn+nginx配置方法
    supervisor的使用
    【linux】杀掉进程命令
    CentOS7 nginx安装与卸载
  • 原文地址:https://www.cnblogs.com/acm-jing/p/4655151.html
Copyright © 2011-2022 走看看