匈牙利算法模板(无算法讲解)
来源:互联网 发布:大数据的主要来源于 编辑:程序博客网 时间: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;}
阅读全文
0 0
- 匈牙利算法模板(无算法讲解)
- poj1469匈牙利算法(模板)
- 匈牙利算法原理讲解
- 匈牙利算法讲解
- 最大匹配算法(匈牙利算法)模板
- hdu1054 匈牙利算法(增广路) (附匈牙利算法模板)
- 匈牙利算法模板
- 匈牙利算法模板
- 匈牙利算法模板
- 【匈牙利算法模板】
- 匈牙利算法模板
- 模板:匈牙利算法
- 匈牙利算法模板
- 匈牙利算法模板
- 匈牙利算法模板
- 【图论】匈牙利算法模板
- 匈牙利算法模板
- 匈牙利算法&模板
- 数组---二分查找
- 关于复选框全选,全不选以及使用按钮传值
- bzoj1668 [Usaco2006 Oct]Cow Pie Treasures 馅饼里的财富(dp)
- 2017.08.05 vao和vbo使用
- python面向对象笔记
- 匈牙利算法模板(无算法讲解)
- div+css实现简单幻灯片动画
- DBCP-template
- 【LeetCode】006.ZigZag Conversion
- C#中如何获取一个二维数组的两维长度,即行数和列数?
- linux中的find查找命令
- redux中间件的认识
- Protocol Buffer Java应用实例
- HDU