网络流24题(更新中
看着别人写网络流24题题解,有点小羡慕,所以照着也来一个网络流24题题解.
2018-08-18 网络流从零开始入门.
----------------------------------------2018-08-18-----------------------------------------------
----------------------------------------2018-08-19-----------------------------------------------
凉凉 开门脆, 直接鸽了2天= =.
----------------------------------------2018-08-20-----------------------------------------------
----------------------------------------2018-08-21-----------------------------------------------
咕咕咕 鸽子愉快的第四天生活. 美滋滋
咕咕咕 咕咕咕 咕咕咕 咕咕咕 咕咕咕 咕咕咕 咕咕咕 咕咕咕 咕咕咕 咕咕咕
(为了清除罪恶感,以上咕咕咕都为手打,绝无粘贴复制 23333 )
OK 我们来开始网络流的第一道题.
1. 飞行员配对方案问题 (二分图模型.
https://www.luogu.org/problemnew/show/P2756
很明显 这是裸的二分图, 所以直接套一个二分图板子就A了...emmmmmmmmmmmm ???????????网络流呢?? 不存在的...明明可以简单二分图干嘛要网络流...(毕竟我还不会 hhhhhh
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <vector> #include <queue> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int maxn = 100024; struct nobe { int to; int lst; }edge[maxn]; int head[128]; int qsz = 1; inline void add(int u, int v) { edge[qsz].lst = head[u]; edge[qsz].to = v; head[u] = qsz++; } int matching[128]; bool check[128]; bool dfs(int u) { int i, v; for (i=head[u]; i; i=edge[i].lst) { v = edge[i].to; if (!check[v]) { check[v] = true; if (matching[v]==-1 || dfs(matching[v])) { matching[v] = u; matching[u] = v; return true; } } } return false; } int GetAns(int n) { int ans = 0; memset(matching, -1, sizeof(matching)); for (int i=1; i<=n; ++i) { if (matching[i] == -1) { memset(check, 0, sizeof(check)); ans += dfs(i); } } return ans; } int main() { int n, m; scanf("%d%d", &m, &n); int u, v; while (scanf("%d%d", &u, &v) && (u!=-1 || v!=-1)) add(u, v); printf("%d\n", GetAns(m)); for (int i=1; i<=m; ++i) if (matching[i] != -1) printf("%d %d\n", i, matching[i]); return 0; }
这道题我直接用dfs写法,,emmm 还有更加优秀的bfs写法, 然后有一个优秀的二分图博客(匈牙利)讲解得贼棒.(32ms)
就是这个博客 http://blog.jobbole.com/106084/#article-comment 由浅入深,娓娓道来, 让人感到 波澜起伏 惊心动魄 扣人心弦 欲罢不能 叹为观止, 惊天动地. (好的,以上成语皆为百度提供.: 搜索 形容讲得非常好的成语
好的 接下来的网络流做法...等...等我再补. 2018-8-21
好的 这是二分图的bfs写法. (23ms) ZZ了把数据类型写错了...调了一个多小时...
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <vector> #include <queue> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int maxn = 100024; struct nobe { int to; int lst; }edge[maxn]; int head[128]; int qsz = 1; inline void add(int u, int v) { edge[qsz].lst = head[u]; edge[qsz].to = v; head[u] = qsz++; } int match[128]; int vis[128]; int prevv[128]; int bfs(int m) { queue<int> Q; int i, j, u, v, ans = 0; memset(match, -1, sizeof(match)); memset(vis, -1, sizeof(vis)); for (i=1; i<=m; ++i) { if (match[i] == -1) { while (!Q.empty()) Q.pop(); Q.push(i); prevv[i] = -1; bool flag = false; while (!Q.empty() && !flag) { u = Q.front(); for (j=head[u]; j && !flag; j=edge[j].lst) { v = edge[j].to; if (vis[v] != i) { vis[v] = i; Q.push(match[v]); if (match[v] >= 0) { prevv[match[v]] = u; } else { flag = true; int d = u, e = v; while (d != -1) { int t = match[d]; match[d] = e; match[e] = d; d = prevv[d]; e = t; } } } } Q.pop(); } if (match[i] != -1) ans++; } } return ans; } int main() { int n, m; scanf("%d%d", &m, &n); int u, v; while (scanf("%d%d", &u, &v) && (u!=-1 || v!=-1)) add(u, v); printf("%d\n", bfs(m)); for (int i=1; i<=m; ++i) if (match[i] != -1) printf("%d %d\n", i, match[i]); return 0; }
----------------------------------------2018-08-22-----------------------------------------------
咕咕咕,学习效率太慢了..二分图原理还不是很多..
感觉最大匹配数分好几种,变个型就不会了. 匈牙利算法- -.
无向图最大匹配数, DAG最大匹配数,二分图最大匹配数,写法都有所不同...但是原理没搞懂啊...
----------------------------------------2018-08-23-----------------------------------------------