The Accomodation of Students 二分图染色 + 匈牙利最大匹配

传送门
思路:n个同学,有的相互认识,问能否划分两组互相不认识的同学,并求出最大的相互认识的同学对数。
先用染色法判断是否是二分图,再使用匈牙利匹配法判断最大的匹配数。

#include<iostream>
#include<vector>
#include<cmath>
#include<cstring>
using namespace std;
vector<int>G[10005], V[10005];
int g[10005], vis[10005], g1[10005];
int n, m;
int sum;
int c1, c2;
int Link[205];
bool Find(int u)
{
    for(int i = 0; i < V[u].size(); i++)
    {
        int v = V[u][i];
        if(!vis[v])
        {
            vis[v] = 1;
            if(Link[v] == -1 || Find(Link[v]))
            {
                Link[v] = u;
                return true;
            }
        }
    }
    return false;
}
int solve()
{
    int cnt = 0;
    memset(Link, -1, sizeof(Link));
    for(int i = 1; i <= n; i++)
    {
        if(V[i].size())
        {
            memset(vis, 0, sizeof(vis));
            if(Find(i)) cnt++;
        }
    }
    return cnt;
}
bool dfs(int u, int col)
{
    vis[u] = col;
    if(col == 0)
        c1++;
    else c2++;
    for(int i = 0; i < G[u].size(); i++)
    {
        int t = G[u][i];
        if(vis[t] == vis[u])
        {
            return false;
        }
        else if(vis[t] == -1)
        {
            if(!dfs(t, !col))
            {
                return false;
            }
        }
    }
    return true;
}
void init(int n)
{
    memset(vis, -1, sizeof vis);
    memset(g, 0, sizeof g);
    memset(g1, 0, sizeof g1);
    for(int i = 1; i <= n; i++)
        G[i].clear();
    for(int i = 1; i <= n; i++)
        V[i].clear();
}
int main()
{
    int T;
    while(cin >> n >> m)
    {
        int u, v;
        init(n);
        for(int i = 1; i <= m; i++)
        {
            cin >> u >> v;
            G[u].push_back(v);
            G[v].push_back(u);
            V[u].push_back(v);
            g[u] = 1;
            g[v] = 1;
        }
        int flag = 0;
        int t = 0;
        for(int i = 1; i <= n ; i++)
        {
            c1 = c2 = 0;
            if(g[i] && vis[i] == -1)
            {
                if(!dfs(i, 0))
                {
                    flag = 1;
                    break;
                }
            }
        }
        if(flag)
            cout << "No" << endl;
        else
        {
            cout << solve() << endl;
        }
    }
    return 0;
}

发布了241 篇原创文章 · 获赞 8 · 访问量 4844

猜你喜欢

转载自blog.csdn.net/weixin_43960370/article/details/104077362
今日推荐