美文网首页
二分匹配 专题整理

二分匹配 专题整理

作者: 染微言 | 来源:发表于2017-07-06 16:09 被阅读43次

二分匹配学习记录

参考资料

二分图讲解及匈牙利模板

HDU 2444

题意

给出图,求是否二分图,和二分图的最大匹配数。

思路

二分图BFS染色+最大匹配。
染色方法就是从起点开始染色,如果上一个点是白色,相邻点就染为黑色。直到碰到矛盾处,就可以知道不是二分图。
最大匹配是通过遍历所有的点,递归更新匹配来扩展匹配。

代码

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

const int maxn = 200+7;

bool maps[maxn][maxn];
int match[maxn], n, vis[maxn];

bool find(int i) { // 匈牙利算法 DFS
    for (int j = 1; j <= n; ++j)
    if (!vis[j] && maps[i][j]) {
        vis[j] = 1;
        if (!match[j] || find(match[j])) {
            match[j] = i;
            return 1;
        }
    }
    return 0;
}

bool isTwo() { // 二分图染色
    queue<int> q;
    memset(vis, 0, sizeof vis);
    q.push(1); vis[1] = 1;
    while (!q.empty()) {
        int s = q.front(); q.pop();
        for (int j = 1; j <= n; ++j) {
            if (!maps[s][j]) continue;
            if (!vis[j]) {
                vis[s]==1?vis[j]=2:vis[j]=1;
                q.push(j);
            }
            else if (vis[j] == vis[s])
                return 0;
        }
    }
    return 1;
}

int main(){
    int m, ans, a, b;
    while (~scanf("%d%d", &n, &m)) {
        ans = 0;
        memset(maps, 0, sizeof maps);
        while (m--) {
            scanf("%d%d", &a, &b);
            maps[a][b] = maps[b][a] = 1;
        }
        if (n==1||!isTwo()) {
            printf("No\n"); continue;
        }
        memset(match, 0, sizeof match);
        for (int i = 1; i <= n; ++i) {
            memset(vis, 0, sizeof vis);
            ans += find(i);
        }
        printf("%d\n", ans/2);
    }
    return 0;
}

HDU 1083

题意

给出一个二分图,求是否能完全匹配。

思路

读入小坑。数组开小所以WA了两次。

之前的2444也算是匈牙利算法的基础版本,这个就是完全版了。都是用DFS过,但是BFS的匈牙利算法效率更高一些。

代码

#include <cstdio>
#include <cstring>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
#define LOCAL

const int maxn = 500+7;

vector<int> maps[maxn];
int p, n, match[maxn];
bool check[maxn];

int dfs(int u) {
    for (int i = 0; i < maps[u].size(); ++i) {
        int v = maps[u][i];
        if(check[v]) continue;
        check[v] = 1;
        if (match[v]==-1 || dfs(match[v])) {
            match[v] = u, match[u] = v;
            return 1;
        }
    }
    return 0;
}

int hungarian () {
    int rt = 0;
    memset(match, -1, sizeof match);
    for (int i = 1; i <= p; ++i) {
        memset(check, 0, sizeof check); // 增广路标记
        rt += dfs(i);
    }
    return rt;
}

void init(){
    scanf("%d%d", &p, &n);
    for (int i = 1; i <= p+n; ++i)
        maps[i].clear();
    for (int i = 1; i <= p; ++i) {
        int x, y; scanf("%d", &x);
        while (x--) {
            scanf("%d", &y);
            maps[i].push_back(p+y);
            maps[p+y].push_back(i);
        }
    }
}

int main(){
#ifdef LOCAL
    freopen("in.txt", "r", stdin);
#endif
    int t;
    while (~scanf("%d", &t))
        while (t--) {
            init();
            hungarian() == p? puts("YES") : puts("NO");
        }
    return 0;
}

相关文章

  • 二分匹配 专题整理

    二分匹配学习记录 参考资料 二分图讲解及匈牙利模板 HDU 2444 题意 给出图,求是否二分图,和二分图的最大匹...

  • 二分图

    二分图判定: 题目链接:二分图判定 dfs: 最大匹配: 题目链接:最大匹配-匈牙利算法 dfs: 二维最大匹配:...

  • KM算法入门

    萌萌的讲解以下为部分摘取最大二分匹配:在一个二分图中找到P->q的一个匹配方案,使得匹配中的边数量不小于任何其他的...

  • 【0326】主题:MECE法则

    MECE法则(相互独立、完全穷尽)相匹配的5种信息分类整理方法: 1. 二分法:把信息分成A和非A两个部分; 2....

  • 2021-10-12leetcode

    快速加 快速幂 二分图的最大匹配 一次A掉

  • 【实战笔记】二分图匹配算法详解

    本笔记主要用于记录与二分图匹配有关的实战。

  • Vim常用匹配、查找、替换命令总结

    今天这篇是整个Vim专题的最后一篇,想看之前的篇目可以进专题详细阅读。 按模式匹配及按原义匹配 ①设置全局大小写敏...

  • 【算法篇】二分图匹配之匈牙利算法

    二分图匹配,自然要先从定义入手,那么二分图是什么呢? 二分图: 二分图又称作二部图,是图论中的一种特殊模型。 设G...

  • 二分图匹配和匈牙利算法

    内容概要: 最大流算法解决二分图最大匹配 匈牙利算法 LeetCode上一个困难问题:覆盖 匹配问题相关概念 该类...

  • 二分图最大匹配

    题目描述 给定一个二分图,结点个数分别为n,m,边数为e,求二分图最大匹配数 输入输出格式 输入格式第一行,n,m...

网友评论

      本文标题:二分匹配 专题整理

      本文链接:https://www.haomeiwen.com/subject/anghhxtx.html