hdu5285-wyh2000 and pupil-(染色法二分图判定)

http://acm.hdu.edu.cn/showproblem.php?pid=5285

题意:把互不认识的人分到两个组,第一组人数尽可能多。

题解:把互不认识的人连起来,当作二分图,二分图可能有多个,对于没有连线的点,扔到第一个图里。二色法对每个二分图染色,记录每个图比较多的颜色的数量累计到答案里。

特判坑:n<=1 或者 m==0

#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<math.h>
#include<string>
#include<map>
#include<queue>
#include<stack>
#include<set>
#define ll long long
#define inf 0x3f3f3f3f
using namespace std;

int n,m;

vector<int>a[100005];
int color[100005];
int zero,one;
int minn,maxx;
bool flag;

void bfs(int x)
{
    queue<int>que;///对x点进行广搜,二色法,一个标记为0,另一个标记为1
    zero=one=0;
    zero++;
    que.push(x);
    color[x]=0;
    while(!que.empty()&&flag)
    {
        int now=que.front();
        que.pop();
        int c=color[now];
        int len=a[now].size();
        for(int i=0;i<len;i++)
        {
            int next=a[now][i];
            if(color[next]==-1)///如果没有被染色过,
            {
                que.push(next);
                if(c==0)
                    color[next]=1,one++;
                else
                    color[next]=0,zero++;
            }
            else ///被染色过
            {
                if( color[next]==c )
                {
                    flag=false;
                    break;
                }
            }
        }

    }
}


int main()//hdu5285
{
    int t;
    scanf("%d",&t);
    while(t--)
    {

        scanf("%d%d",&n,&m);

        for(int i=1;i<=n;i++)
            a[i].clear();
        memset(color,-1,sizeof(color));
        minn=maxx=0;
        flag=true;

        if(n<=1)
        {
            printf("Poor wyh\n");
            continue;
        }
        if(m==0)///特判,否则全部染成0色
        {
            printf("%d 1\n",n-1);
            continue;
        }

        while(m--)
        {
            int u,v;
            scanf("%d%d",&u,&v);
            a[u].push_back(v);
            a[v].push_back(u);
        }
        int no=0;///没有被染色的点,其中第一组尽量多,则把没有染色的加到多的那一边去
        for(int i=1;i<=n && flag;i++)
        {

            if(color[i]==-1 && a[i].size() )///没有被染色的点 并且 不是独立的
            {
                bfs(i);
                if(zero<one)
                    swap(zero,one);
                maxx+=zero;
                minn+=one;
            }
            else if(color[i]==-1 && a[i].size()==0)///独立的点染成颜色0,0是第一组,较多的那一组
            {
                color[i]=0;
                maxx++;
            }
        }
        if(flag)
            printf("%d %d\n",maxx,minn);
        else
            printf("Poor wyh\n");
    }

    return 0;
}

 

posted @ 2019-08-06 19:26  守林鸟  阅读(154)  评论(0编辑  收藏  举报