《啊哈!算法》我要做月老 ——二分图最大匹配

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zhaohaibo_/article/details/82025159
题目描述

小哼今天和小伙伴们一起去游乐场玩,终于可以坐上梦寐以求的过山车了。过山车的每一排只有两个座位,为了安全起见,是每个女生必须和一个男生做一排。但是,每个人都希望与自己认识的人坐在一起。如何安排才可以让更多认识的男生和女生坐在一起呢?

输入

输入第一行为两个整数n,m。n表示有n个人(其中前1~n/2号为女生,n/2+1~n号为男生),m表示有m个关系。(1 < n,m < 10)

后面m行,每行两个数a,b,表示a和b互相认识。

输出

输出最大匹配个数(最多有几对男生女生可以坐在一起)

样例输入

6 5
1 4
1 5
2 5
2 6
3 4

样例输出

3

数组法

#include <bits/stdc++.h>
using namespace std;
int cnt,ihead[10],mc[10];
bool vis[10];
bool dfs(int x,vector<vector<int> >vec){
    for(vector<int>::const_iterator it = vec[x].begin();it!=vec[x].end();++it){
        int y = *it;
        if(!vis[y]){
            vis[y] = 1;
            if(!mc[y] || dfs(mc[y],vec)){
                mc[x]=y;
                mc[y]=x;
                return true;
            }
        }
    }
    return false;
}
int main(){
    int n,m;
    scanf("%d%d",&n,&m);
    vector<vector<int> >vec(n+1);
    for(int i=1;i<=m;i++){
        int a,b;
        scanf("%d%d",&a,&b);
        vec[a].push_back(b);
        vec[b].push_back(a);
    }
    int ans = 0;
    for(int i=1; i<=n/2; ++i)
        if(!mc[i]){
            memset(vis, 0, sizeof(bool) * (n + 1));
            if(dfs(i,vec))
                ++ans;
        }
    printf("%d",ans);

}

邻接表法

#include <bits/stdc++.h>
using namespace std;
const int N = 505*2, M= N * N;
struct E{
    int next,to;
}e[M];
//mc:表示每个点所匹配到的另一个点match
//vis:Y集元素是否被访问过
int cnt,ihead[N],mc[N];
bool vis[N];
void add(int x,int y){
    e[++cnt].next = ihead[x];
    e[cnt].to = y;
    ihead[x] = cnt;
}
//匈牙利算法
//x:x集上的点,从当前点出发找增广路
//返回值:若找到增广路则返回true,否则返回false
bool dfs(int x){
    for(int i=ihead[x]; i; i=e[i].next){
        int y = e[i].to;
        if(!vis[y]){//如果找到一个Y集上的点没有标记
            vis[y] = true;//标记该点
            //如果y是没有匹配点的,说明找到了一条增广路;或者说递归查找y的匹配点,得到了一条增广路
            if(mc[y] == 0 || dfs(mc[y])){
                //找到了增广路,更新mc数组
                mc[x] = y;
                mc[y] = x;
                return true;
            }
        }
    }
    return false;
}
int main(){
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++){
        int a,b;
        scanf("%d%d",&a,&b);
        add(a,b);
        add(b,a);
    }
    int ans = 0;
    for(int i=1; i<=n/2; ++i)
        if(!mc[i]){
            //如果x集中的第i个点没有匹配到Y集上的点,则从这个点出发寻找增广路
            memset(vis, 0, sizeof(bool) * (n + 1));
            //将数组置为0
            if(dfs(i))
                ++ans;//如果找到,答案直接+1
        }
    printf("%d",ans);
    return 0;   
}

猜你喜欢

转载自blog.csdn.net/zhaohaibo_/article/details/82025159