Dinic 二分图最大匹配最大流解法(来自lixiyi学姐的模板
2017-07-25 10:47
471 查看
/* Dinic算法,复杂度O(V^2E) 总是寻找最短的增广路,并沿着它增广 实际运行速度快,可以用作模板 */ const int inf = 2147483647; const double eps = 1e-8; const int maxn = 505; const ll mod = 1e9+7; struct edge{ int to, cap, rev; }; vector<edge> G[maxn]; int level[maxn]; //各点所属层数 int iter[maxn]; //iter可以避免对没有用的边进行多次检查 void addedge(int from, int to, int cap){ G[from].push_back((edge){to, cap, (int)G[to].size()}); G[to].push_back((edge){from, 0, (int)G[from].size()-1}); } //构造分层图 void bfs(int s){ memset(level, -1, sizeof(level)); queue<int> q; level[s] = 0; q.push(s); while(!q.empty()){ int v = q.front(); q.pop(); for(int i=0; i<G[v].size(); i++){ edge &e = G[v][i]; if(e.cap>0 && level[e.to]<0){ //边容量大于0且还为给定层数 level[e.to] = level[v]+1; q.push(e.to); } } } } //dfs寻找增广路 int dfs(int v, int t, int f){ if(v == t) return f; //已经到了终点t for(int &i = iter[v]; i<G[v].size(); i++){ //i从iter[v]处开始检查,&:修改i时,iter也会修改 edge &e = G[v][i]; if(e.cap > 0 && level[v]<level[e.to]){ //可增广,且属于v的下一层 int d = dfs(e.to, t, min(f, e.cap)); if(d>0){ e.cap -= d; G[e.to][e.rev].cap += d; return d; } } } return 0; } int max_flow(int s, int t){ int flow = 0; for( ;; ){ bfs(s); //构建分层图 if(level[t]<0) return flow; //到终点的分层图已经造不出来了,即求出了最大流 memset(iter, 0, sizeof(iter)); int f; while((f = dfs(s, t, inf))>0){ flow += f; } } } int main(){ int n, m; scanf("%d%d", &n, &m); //注意下标转成从0开始 for(int i=0; i<m; i++){ int u, v, cap; scanf("%d%d%d", &u, &v, &cap); addedge(--u, --v, cap); } int ans = max_flow(0, n-1); printf("%d\n", ans); return 0; }
#include<iostream> #include<queue> #include<stack> #include<vector> #include<set> #include<math.h> #include<string.h> #include<stdlib.h> #include<stdio.h> #include<string> #include<map> #include<algorithm> #include<sstream> //#include<ctype.h> using namespace std; typedef long long ll; //typedef pair<int, int> P; /* 二分图最大匹配最大流简化做法,复杂度O(|V||E|) */ const int inf = 2147483647; const double eps = 1e-8; const int maxn = 505; const ll mod = 1e9+7; int n, k; vector<int> G[maxn]; int match[maxn]; //匹配 bool used[maxn]; void addedge(int u, int v){ G[u].push_back(v); G[v].push_back(u); } //dfs寻找增广路 bool dfs(int v){ used[v] = true; for(int i=0; i<G[v].size(); i++){ int u = G[v][i], w = match[u]; if(w<0 || !used[w] && dfs(w)){ //u未匹配过,或还有增广路 match[v] = u; match[u] = v; return true; } } return false; } //求解二分图的最大匹配 int bipartite_matching(){ int res = 0; memset(match, -1, sizeof(match)); for(int v = 0; v<n+k; v++){ if(match[v] < 0){ memset(used, 0, sizeof(used)); if(dfs(v)){ res++; } } } return res; } int main(){ while(scanf("%d%d", &n, &k) == 2){ for(int i=0; i<n+k; i++){ G[i].clear(); } for(int i=0; i<n; i++){ int m; scanf("%d", &m); for(int j=0; j<m; j++){ int b; scanf("%d", &b); addedge(i, n+b-1); } } printf("%d\n", bipartite_matching()); } return 0; } input: 5 5 2 2 5 3 2 3 4 2 1 5 3 1 2 5 1 2 n=5 m=5 5只奶牛 5个谷仓 每只奶牛可以去那些谷仓数目 谷仓编号
相关文章推荐
- 二分图最大匹配模板【匈牙利;Dinic最大流】
- 匈牙利算法求二分图的最大匹配/匈牙利算法模板
- hdu3829及二分图最大匹配模板
- Hopcroft-Karp算法模板(解决二分图最大匹配问题)
- 透彻解析二分图最大匹配匈牙利算法模板
- 二分图最大匹配(匈牙利算法Dfs模板)
- 二分图最大权匹配 、 最小权匹配 模板
- HDU2063——过山车——————【二分图最大匹配模板】
- (资料)二分图(偶图)最大匹配解法之一匈牙利算法
- NYOJ 题目239 月老的难题 (二分图最大匹配-匈牙利算法模板)
- 【匈牙利算法】二分图最大匹配(模板)
- 二分图最大权最小权完美匹配模板KM
- 二分图最大匹配之匈牙利算法模板
- POJ-1274 The Perfect Stall (二分图最大匹配模板题)
- 二分图最大匹配算法模板
- [HDU]2444 The Accomodation of Students二分图最大流匹配模板
- 二分图最大匹配算法-匈牙利算法(Hungary)模板
- [模板] + [详解] - 二分图最大匹配 - 匈牙利算法
- hdoj--1045<dfs&二分图最大匹配>(这里是dfs解法)
- 【HDU 2063】过山车(二分图最大匹配模板题)