二分图板子

Posted vikyanite

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了二分图板子相关的知识,希望对你有一定的参考价值。

二分图最大匹配:

匈牙利算法  邻接表O(mn):

技术图片
#pragma GCC optimize(2)
#include <bits/stdc++.h>
using namespace std;

const int maxn = 1010;
const int maxm = 2e5;
int n, m, t;
int mch[maxn], vistime[maxn];

struct E {
    int to, next;
}edge[maxm];

int tot, head[maxn];

void init()
{
    memset(vistime, 0, sizeof(vistime));
    memset(head, -1, sizeof(head));
    tot = 0;
}

inline void add_edge(int u, int v) {
    edge[tot].to = v;
    edge[tot].next = head[u];
    head[u] = tot++;
}

bool Hungarian(int u, int tag) {
    if (vistime[u] == tag) return 0;
    vistime[u] = tag;
    for (int i = head[u]; i != -1; i = edge[i].next) {
        int v = edge[i].to;
        if ((mch[v] == 0) || Hungarian(mch[v], tag)) {
            mch[v] = u;
            return 1;
        }
    }
    return 0;
}

int main() {
    scanf("%d%d%d", &n, &m, &t);
    init();
    while (t--) {
        int u, v;
        scanf("%d%d", &u, &v);
        add_edge(u, v);
    }
    int ans = 0;
    for (int i = 1; i <= n; ++ i)
        if (Hungarian(i, i))
            ++ans;
    printf("%d
", ans);
    return 0;
}
View Code

KM算法  O(N^3):

技术图片
#include <bits/stdc++.h>
using namespace std;

const int maxn = 501;
const int maxm = 250001;
const int inf = 0x3f3f3f3f;

int nl, nr, m;
int tot, head[maxn];
int ans, linkx[maxn], linky[maxn];
int dx[maxn], dy[maxn];

struct E {
    int to, next;
}edge[maxm]; //这里千万要注意,如果题目是双向边的话,这里的N要开2*N

inline void read(int& ans)
{
    int x = 0, f = 1;
    char ch = getchar();
    while (ch<0 || ch > 9) {
        if (ch == -) f = -1;
        ch = getchar();
    }
    while ( ch >= 0 && ch <= 9) {
        x = x * 10 + ch - 0;
        ch = getchar();
    }
    ans =  x * f;
}
//加边
inline void add_edge(int u, int v) {
    edge[tot].to = v;
    edge[tot].next = head[u];
    head[u] = tot++;
    if (!linkx[u] && !linky[v])
        linky[v] = u, linkx[u] = v, ++ ans;
}

bool bfs()
{
    bool ret=0;
    queue<int> q;
    memset(dx, 0, sizeof(dx)), memset(dy, 0, sizeof(dy));
    for (int i = 1; i <= nl; ++ i)
        if (!linkx[i]) q.push(i);
    while (!q.empty()) {
        int u = q.front(); q.pop();
        for (int i = head[u]; ~i; i = edge[i].next) {
            int v = edge[i].to;
            if (!dy[v]) {
                dy[v] = dx[u] + 1;
                if (!linky[v]) ret = 1;
                else dx[linky[v]] = dy[v]+1, q.push(linky[v]);
            }
        }
    }
    return ret;
}

bool dfs(int u)
{
    for (int i = head[u]; ~i; i = edge[i].next) {
        int v = edge[i].to;
        if (dy[v] == dx[u] + 1) {
            dy[v] = 0;
            if (!linky[v] || dfs(linky[v])) {
                linky[v] = u, linkx[u] = v;
                return 1;
            }
        }
    }
    return 0;
}

int main()
{
    int a, b;
    memset(head, -1, sizeof(head));
    read(nl), read(nr), read(m);
    for (int i = 1; i <= m; ++ i)
        read(a), read(b), add_edge(a,b);

    while(bfs()) {
        for (int i = 1; i <= nl; ++ i)
            if (!linkx[i] && dfs(i))
                ++ ans;
    }

    printf("%d
",ans);
//  这段循环是用来输出跟谁匹配 
//    for (int i = 1; i <= nl; ++ i)
//        printf("%d ",linkx[i]);

    return 0;
}
View Code

 

以上是关于二分图板子的主要内容,如果未能解决你的问题,请参考以下文章

iContact卷曲子代码

创建广告时出现代码 200 和子代码 1487194 的 Facebook 错误背后的原因是啥?

在 SpriteKit 中出现错误。 - 线程 1:EXC_BREAKPOINT(代码=1,子代码=0x1007351fc)

Facebook OAuthException代码190子代码490 - 用户注册了阻塞的登录检查点

斯威夫特 3 - 'EXC_BAD_INSTRUCTION(代码 = EXC_1386_INVOP,子代码 = 0x0)' 错误

错误 - 线程 1 exc_bad_instruction(代码=exc_1386_invop 子代码=0x0)