OpenJPOJ1013_Excellent Note_Dinic算法求二分图匹配
2017-08-22 16:48
399 查看
题意
求给出正则二分图的最大匹配。思路
匈牙利算法果断TLE,用dinic算法求解二分图匹配。算法过程
1.读入正则二分图,dfs黑白染色2.在染色图上建立跑dinic的图。s到白点,白点到黑点,黑点到t,权值都是1。这里存图有一定技巧,在方便地找反向边地同时,还能保证原边的位号都是偶数,方便最后输出结果。
3.dinic算法,输出结果。
链接
https://vjudge.net/contest/179392#problem/D代码
#include<cstdio> #include<iostream> #include<cstring> #include<vector> #include<queue> using namespace std; const int maxn = 1e5 + 10; const int maxm = 1e6 + 10; const int maxe = maxn * 2 + maxm; const int inf = 0x3f3f3f3f; struct edge{ int to, cap, next; }; int n, m; int x, y; vector<int> G[maxn]; int mark[maxn]; int head[maxn], tt; edge E[maxe]; int level[maxn], iter[maxn]; void dfs0(int v, int c) { mark[v] = c; for(int i = 0; i < G[v].size(); i++) { int d = G[v][i]; if(mark[d] < 0) { dfs0(d, c ^ 1); } } } void get_color() { memset(mark, -1, sizeof mark); for(int i = 1; i <= n; i++) { if(mark[i] >= 0) continue; dfs0(i, 0); } } void add(int from, int to, int cap) { E[tt].to = to, E[tt].cap = cap, E[tt].next = head[from], head[from] = tt, tt++; } void build_g(int s, int t) { tt = 0; memset( 4000 head, -1, sizeof head); for(int i = 1; i <= n; i++) { if(mark[i] == 0) { add(s, i, 1); add(i, s, 0); for(int j = 0; j < G[i].size(); j++) { int d = G[i][j]; add(i, d, 1); add(d, i, 0); } } else{ add(i, t, 1); add(t, i, 0); } } } void bfs(int s) { memset(level, -1, sizeof level); queue<int> qu; level[s] = 0; qu.push(s); while(qu.size()) { int v = qu.front(); qu.pop(); for(int i = head[v]; i != -1; i = E[i].next) { edge e = E[i]; if(e.cap > 0 && level[e.to] < 0) { level[e.to] = level[v] + 1; qu.push(e.to); } } } } int dfs(int v, int t, int f) { if(v == t) return f; for(int &i = iter[v]; i != -1; i = E[i].next) { edge &e = E[i]; if(e.cap > 0 && level[e.to] > level[v]) { int d = dfs(e.to, t, min(f, e.cap)); if(d > 0) { e.cap -= d; E[i^1].cap += d; return d; } } } return 0; } int dinic(int s, int t) { int flow = 0; while(1) { bfs(s); if(level[t] < 0) return flow; for(int i = s; i <= t; i++) iter[i] = head[i]; while(1) { int f = dfs(s, t, inf); if(f == 0) break; flow += f; } } } void output() { for(int i = 0; i < tt; i += 2) { if(E[i].cap == 0) { if(E[i].to == 0 || E[i].to == n+1) continue; if(E[i^1].to == 0 || E[i^1].to == n+1) continue; cout << E[i].to << " " << E[i^1].to << endl; } } } int main() { scanf("%d %d", &n, &m); for(int i = 0; i < m; i++) { scanf("%d %d", &x, &y); G[x].push_back(y); G[y].push_back(x); } get_color(); int s = 0, t = n + 1; build_g(s, t); dinic(s, t); output(); return 0; }
相关文章推荐
- nyoj-239 月老的难题 (二分图匹配—匈牙利算法 && 网络流—Dinic算法)
- [Note]关于Python中文编码出现乱码的解决方案(涉及urllib.urlopen(),open()等函数)
- Open Yale Course--Financial Market--Note1 zz
- Codevs_P1922 骑士共存问题(Dinic算法最大流+二分图匹配)
- OpenWrt's Release Note and Version info
- Poj 1013 Counterfeit Dollar / OpenJudge 1013(2692) 假币问题
- Dinic算法实现二分图匹配
- Two Excellent MyBatis Open Source Tools
- 二分图匹配
- The Perfect Stall - POJ 1274 二分图匹配
- note-Javascript::string2Date for new Date(str)
- OpenXLive Push Notification Hosting服务开发指南
- linux配置open*** 客户端windows
- Computer Vision Foundation open access
- BZOJ 1059: [ZJOI2007]矩阵游戏 二分图匹配
- hello openwrt
- 棋盘游戏 - HDU 1281 二分图匹配
- too many open files
- libstdc++.so.5: cannot open shared object file: No such file or directory