匈牙利算法模板(无算法讲解)
2017-08-05 22:24
106 查看
二分图最大匹配和匈牙利算法想学习知识点的误入
二分图及匹配的定义不介绍(还是那句话,网上有很多相关资料,说白了就是我懒)匈牙利算法,总的来说就是对于每个点出发找增广路,找到一个非匹配点就连,如果找不到就去在增广路上抢别的点的匹配点,然后让别的点换地方。(网上还是有很多资料)
其实这篇文章我就是想来贴两道陈芝麻烂谷子的模板题。。。
模板题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 ; bool vis ; 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 , cnt, n, k, mth ; bool vis ; struct edge {int to, next;} e[N*N]; struct point {int x, y;} a , b ; 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; }
相关文章推荐
- AtCoder Regular Contest 092 C - 2D Plane 2N Points 贪心 匈牙利算法模板
- 51Nod 飞行员配对(二分图最大匹配)(匈牙利算法模板题)
- 【模板】匈牙利算法 二分图最大匹配题模板
- 二分匹配(匈牙利算法)模板
- 二分图匹配--匈牙利算法模板
- 匈牙利算法模板及解释
- 二分匹配(匈牙利算法)【模板】
- AtCoder Regular Contest 092 C - 2D Plane 2N Points 贪心 匈牙利算法模板
- 匈牙利算法原理讲解
- 【二分匹配】【匈牙利算法即由增广路求最大匹配模板】
- poj-3041-匈牙利算法模板
- poj1469匈牙利算法(模板)
- hdu 2063 过山车(匈牙利算法模板)
- 二分图匹配(匈牙利算法模板)
- 透彻解析二分图最大匹配匈牙利算法模板
- HDU 2444 The Accomodation of Students(最大二分匹配(匈牙利算法)+二分图判断->模板题目)
- 二分图的匈牙利算法 HDU 2063(裸模板,待增加)
- HDU 2063 过山车(匈牙利算法模板)
- 模板:匈牙利算法
- 匈牙利算法模板