匈牙利算法模板(无算法讲解)

来源:互联网 发布:大数据的主要来源于 编辑:程序博客网 时间:2024/05/20 10:51

二分图最大匹配和匈牙利算法想学习知识点的误入

二分图及匹配的定义不介绍(还是那句话,网上有很多相关资料,说白了就是我懒

匈牙利算法,总的来说就是对于每个点出发找增广路,找到一个非匹配点就连,如果找不到就去在增广路上抢别的点的匹配点,然后让别的点换地方。(网上还是有很多资料


其实这篇文章我就是想来贴两道陈芝麻烂谷子的模板题。。。

模板题1

https://www.luogu.org/problem/show?pid=3386 【模板】二分图匹配

这道题目不会的,应该去看所谓的“很多资料”。

题解:匈牙利算法(您略长、复杂度玄学的Dinic算法等也可)

代码:

#include <bits/stdc++.h>using namespace std;const int N = 1005;int cnt, head[N<<1], mth[N]; bool vis[N];struct edge {int to, next;} e[N*N];void addedge (int u, int v) {    e[++cnt] = (edge){v, head[u]}; head[u] = cnt;}bool hgy (int x) {    for (int i = head[x]; i; i = e[i].next)        if (!vis[e[i].to]) {            vis[e[i].to] = 1;            if (!mth[e[i].to] || hgy (mth[e[i].to])) {                mth[e[i].to] = x; return 1;            }        }    return 0;}int main () {    int n, m, ec, u, v, ans = 0;    scanf ("%d%d%d", &n, &m, &ec);    for (int i = 1; i <= ec; ++ i) {        scanf ("%d%d", &u, &v);        if (u<=n && v<=m) addedge (u, v);    }    for (int i = 1; i <= n; ++ i) {        memset (vis, 0, sizeof (vis));        if (hgy (i)) ++ ans;    } printf ("%d\n", ans);    return 0;}

来一道升级一点的模板

模板题2

http://www.lydsy.com/JudgeOnline/problem.php?id=2663 [Beijing wc2012]灵魂宝石

R对K有单调性,所以可以二分。rmin直接跑最大匹配就行;rmax可以理解成求一个最小的极大匹配(不知道对不对),大概就是把分属于两个集合在原图中没有边的点在新图连边,有边的新图中不连边,然后用(n-最大匹配数)与k的大小关系作为判断的条件。大概是因为如果这样的匹配出来是k,说明对于当前的R,不可能有小于k的匹配满足条件,这样就能算出r的最大值。

代码:

#include <bits/stdc++.h>using namespace std;typedef double DB;const int N = 105;const DB eps = 1e-8;int head[N], cnt, n, k, mth[N];bool vis[N];struct edge {int to, next;} e[N*N];struct point {int x, y;} a[N], b[N];int cmp (DB a, DB b) {    if (a-b>=0 && a-b<=eps) return 0;    if (b-a>=0 && b-a<=eps) return 0;    if (a-b>0) return 1; return -1;}int judis (point A, point B, DB d) {    int dx = A.x-B.x, dy = A.y-B.y;    DB dis = 1.0*dx*dx+dy*dy;    return cmp (dis, d*d);}void addedge (int u, int v) {    e[++cnt] = (edge){v, head[u]}; head[u] = cnt;}void init () {    cnt = 0;    memset (head, 0, sizeof (head));    memset (mth, 0, sizeof (mth));    for (int i = 1; i <= n*n; ++ i) {        e[i].to = e[i].next = 0;    }}bool hgy (int x) {    for (int i = head[x]; i; i = e[i].next)        if (!vis[e[i].to]) {            vis[e[i].to] = 1;            if (!mth[e[i].to] || hgy (mth[e[i].to])) {                mth[e[i].to] = x; return 1;            }        }    return 0;}bool Match (bool fl, DB r) {    int ans = 0; init ();    for (int i = 1; i <= n; ++ i)        for (int j = 1; j <= n; ++ j) {            if (fl && judis (a[i], b[j], r)<=0) addedge (i, j);            if (!fl && judis (a[i], b[j], r)>=0) addedge (i, j);        }    for (int i = 1; i <= n; ++ i) {        memset (vis, 0, sizeof (vis));        if (hgy (i)) ++ ans;     }    if (fl && ans>=k) return 1;    if (!fl && ans>=n-k) return 1;    return 0;}int main () {    DB l, r, mid; scanf ("%d%d", &n, &k);    for (int i = 1; i <= n; ++ i)        scanf ("%d%d", &a[i].x, &a[i].y);    for (int i = 1; i <= n; ++ i)        scanf ("%d%d", &b[i].x, &b[i].y);    l = 0, r = 1e6;    for (int i = 1; i <= 45; ++ i) {        mid = (l+r)/2;        if (Match (1, mid)) r = mid;        else l = mid;    }    printf ("%.2lf ", l);    if (n==k) {puts ("+INF"); return 0;}    l = 0, r = 1e6;    for (int i = 1; i <= 45; ++ i) {        mid = (l+r)/2;        if (Match (0, mid)) l = mid;        else r = mid;    }    printf ("%.2lf\n", l);    return 0;}
原创粉丝点击