大意:给你一些人,有些相互认识,有些不认识,问你是否能将不认识的分在一组,如果不能,输出No,如果可以,输出可以预定的双人间的最大值。

思路:

1、交叉染色法判断二分图。

2、二分图最大匹配。

我敲的时候出现了小错误,然后爆栈了。以为是DFS太多导致,于是我改用队列实现的交叉染色,过了。敲二分匹配时突然发现了一个小错误,明白了是这个导致了爆栈。然后回过头去改DFS实现的交叉染色,Hdu的数据实在是太水了,有些地方我一不小心改成错误的,还是过了,但这在UVA上是绝对过不了的,比如UVA 10004二分染色。

CODE:

 

#include <iostream>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <queue>
using namespace std;

const int MAXN = 210;
const int MAXM = 210*210;

struct Edge
{
    int v, next;
}edge[MAXM];

int n, m;
int cnt;

int first[MAXN], link[MAXN];
bool vis1[MAXN], color[MAXN], vis2[MAXN];

void init()
{
    cnt = 0;
    memset(first, -1sizeof(first));
    memset(vis1, 0sizeof(vis1));
    memset(color, 0sizeof(color));
    memset(link, -1sizeof(link));
}

void read_graph(int u, int v)
{
    edge[cnt].v = v;
    edge[cnt].next = first[u], first[u] = cnt++;
}

void read_graph2()
{
    while(m--)
    {
        int u, v;
        scanf("%d%d", &u, &v);
        read_graph(u, v);
        read_graph(v, u);
    }
}

queue<int> q;
int Bicolor(int src)
{
    while(!q.empty()) q.pop();
    vis1[src] = 1;
    q.push(src);
    while(!q.empty())
    {
        int u = q.front(); q.pop();
        for(int e = first[u]; e != -1; e = edge[e].next)
        {
            int v = edge[e].v;
            if(!vis1[v])
            {
                vis1[v] = 1;
                color[v] = !color[u]; //写错了,写成color[v] = !color[v]也过,Hdu数据太水了。
                q.push(v);
            }
            else if(color[u] == color[v]) return false;
        }
    }
    return true;
//队列实现的交叉染色 

/*int Bicolor(int u) //DFS实现的交叉染色 
{
    for(int e = first[u]; e != -1; e = edge[e].next)
    {
        int v = edge[e].v;
        if(!vis1[v])
        {
            vis1[v] = 1;
            color[v] = !color[u];
            Bicolor(v);
        }
        else if(color[u] == color[v]) return false; 
    }
    return true;
}
*/

int ED(int u)
{
    for(int e = first[u]; e != -1; e = edge[e].next)
    {
        int v = edge[e].v;
        if(!vis2[v])
        {
            vis2[v] = 1//写成vis2[1] = 1;爆栈了。。。 
            if(link[v] == -1 || ED(link[v]))
            {
                link[v] = u;
                return true;
            }
        }
    }
    return false;
}

void solve(int src)
{
    int ans = 0;
    vis1[src] = 1//很重要,不然会WA。 
    if(!Bicolor(src))
    {
        printf("No\n");
        return ;
    }
    for(int i = 1; i <= n; i++) 
    {
        memset(vis2, 0sizeof(vis2));
        if(ED(i)) ans++;
    }
    printf("%d\n", ans/2);
}

int main()
{
    while(~scanf("%d%d", &n, &m))
    {
        init();
        read_graph2();
        solve(1);
    }
    return 0;
}

 

posted on 2012-11-06 12:58  有间博客  阅读(428)  评论(0编辑  收藏  举报