HDU 2444 The Accomodation of Students(二分图判定+最大匹配)

  这是一个基础的二分图,题意比较好理解,给出n个人,其中有m对互不了解的人,先让我们判断能不能把这n对分成两部分,这就用到的二分图的判断方法了,二分图是没有由奇数条边构成环的图,这里用bfs染色法就可以判断,其次让我们求分在两部分的最大对数,这就是二分图的最大匹配问题,这里数据只有200,所以匈牙利算法求蹭广路径的办法可以解决这个问题,也相对比较容易编写。

另外一开始我链式前向星的数组开小了,G++居然返回超时,后来换了C++才RE,想到数组越界的问题,不得不说这些编译器真傲娇啊~

#include<iostream>
#include<cstring>
#include<queue>
#include<cstdio>
using namespace std;
struct EDGE
{
    int to,nxt;
}edge[50000];
int head[220],n,m,tot;
void add_edge(int x,int y)
{
    edge[tot].to = y;
    edge[tot].nxt = head[x];
    head[x] = tot++;
}
int clo[220];
bool bfs(int id)
{
    queue<int>que;
    clo[id] = 1;
    while(!que.empty()) que.pop();
    que.push(id);
    while(!que.empty())
    {
        int now = que.front();
        que.pop();
        for(int i = head[now];i != -1;i = edge[i].nxt)
        {
            int go = edge[i].to;
            if(clo[go] == -1)
            {
                clo[go] = (clo[now] ^ 1);
                que.push(go);
            }
            else if(clo[go] == clo[now]) return false;
        }
    }
    return true;
}
bool is_erfen()
{
    memset(clo,-1,sizeof(clo));
    bool mark = true;
    for(int i = 1;i <= n;i++)
    {
        if(clo[i] != -1)continue;
        mark = bfs(i);
        if(mark == false) return false;
    }
    return mark;
}
int vis[220],link[220];
bool Find(int x)
{
    for(int i = head[x];i != -1;i = edge[i].nxt)
    {
        int now = edge[i].to;
        if(vis[now]) continue;
        vis[now] = 1;
        if(link[now] == -1 || Find(link[now]))
        {
            link[now] = x;
            return true;
        }
    }
    return false;
}
int match()
{
    memset(link,-1,sizeof(link));
    int ans = 0;
    for(int i = 1;i <= n;i++)
    {
        memset(vis,0,sizeof(vis));
        if(Find(i))
            ans++;
    }
    return ans / 2;
}
int main()
{
    while(~scanf("%d%d",&n,&m))
    {
        tot = 0;
        memset(head,-1,sizeof(head));
        for(int i = 0;i < m;i++)
        {
            int u,v;
            scanf("%d%d",&u,&v);
            add_edge(u,v);
            add_edge(v,u);
        }
        bool flag = is_erfen();
        if(!flag)
        {
            printf("No
");
        }
        else printf("%d
",match());
    }
    return 0;
}
原文地址:https://www.cnblogs.com/jifahu/p/5479143.html