P3386 【模板】二分图最大匹配

题目传送门

#include <bits/stdc++.h>

using namespace std;
const int N = 510;
const int M = 100010;

int n1, n2;                 //左边有n1个点,右边有n2个点
int m;                      //共有m条边
int h[N], e[M], ne[M], idx; //链式前向星

int match[N]; //右边点对应的左边哪个点
bool st[N];   //是不是已经匹配过
int res;      //记录结果数值,成功匹配的对数

//链式前向星建图
void add(int a, int b) {
    e[idx] = b, ne[idx] = h[a], h[a] = idx++;
}

/**
 * 功能:为每个男生找妹子
 * @param x
 * @return
 */
bool find(int u) {
    //枚举每一个看上的集合
    for (int i = h[u]; ~i; i = ne[i]) {
        int j = e[i];
        if (!st[j]) {     //本轮次匹配时,没有男生相中的女生(动态,临时概念)
            st[j] = true; //有人相中了
            // match[j] == 0:如果j女生以前没有男朋友,那OK,可以
            // find(match[j]):如果j的男朋友match[j]可以找其它女生
            if (match[j] == 0 || find(match[j])) {
                //设置女生j的男朋友是u,逆袭成功!
                match[j] = u;
                return true;
            }
        }
    }
    return false;
}

int main() {
    //左边点数,右边点数,m条边
    cin >> n1 >> n2 >> m;
    //初始化邻接表
    memset(h, -1, sizeof h);
    //读入m条边建图
    for (int i = 0; i < m; i++) {
        int a, b;
        cin >> a >> b;
        //存的是左边指向右边,因为在代码中只找左边进行梳理,不会去遍历右边,所以只存一边
        //不必保存右边结点指向左边结点的边
        add(a, b);
    }
    //枚举左侧的每个点
    for (int i = 1; i <= n1; i++) {
        //表示后来的更牛,它看上的妹子,就会让其它人让出来,都是没有人选择过的状态!
        //就是本轮状态标识的作用,而不是全局状态标识
        memset(st, false, sizeof st);
        //如果成功找到妹子,个数加1
        if (find(i)) res++;
    }
    //输出结果
    printf("%d\n", res);
    return 0;
}
posted @   糖豆爸爸  阅读(52)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
历史上的今天:
2020-04-05 MySQL性能测试--分区和分表测试
Live2D
点击右上角即可分享
微信分享提示