网络流总结
来源:互联网 发布:淘宝零食店 知乎 编辑:程序博客网 时间:2024/05/19 19:57
简要总结以下网络流的学习.
参考资料
《挑战程序设计竞赛》
《算法竞赛入门经典》-刘汝佳
《算法导论》
最大流
符号说明
f(u,v) u,流向 v 的流量c(u,v) u, v 的容量s,t 源点和汇点
流网络
一个流网络总是满住以下限制条件的
流量限制: 对于任意的节点
流量守恒: 任意顶点
在最大流问题中我们要找到从源点到汇点的最大流量
反向边
反向边可以这样理解,从
残留网络(residual network)
从直观上看,给定流网络
cf(u,v)=⎧⎩⎨⎪⎪c(u,v)−f(u,v)f(u,v)0 若(u,v)∈E 若(v,u)∈E(反向边) 其他
Ford-Fulkerson方法
这是一类算法,而不是一个算法。简单的说就是
1. 初始化flow = 0;
2.
3. 沿着增广路增广.
用朴素的深搜找增广路的方法的复杂度是
Dinic
struct Edge{ int from,to,cap; Edge(int u,int v,int c = 0):from(u),to(v),cap(c){};};//残量网络void add_edge(int u,int v,int cap){ E.push_back(Egde(u,v,cap));G[u].push_back(E.size()-1); E.push_back(Edge(v,u,0)); G[v].push_back(E.size()-1);}struct Dinic{ std::vector<Edge> E; std::vector<int> G[MAX_V]; int level[MAX_V],cur[MAX_V];//分层,当前弧; void bfs(int s){ memset(level,-1,sizeof(level)); queue<int> Q;Q.push(s); level[s] = 0; while (!Q.empty()) { int u = Q.front();Q.pop(); for(int i=0 ; i<G[u].size() ; ++i){ Edge & e = E[G[u][i]]; if(e.cap>0 && level[e.to]<0){ level[e.to] = level[u]+1; Q.push(e.to); } } } } int dfs(int v,int t,int f){ if(v==t || f == 0)return f; for(int& i = cur[v] ; i<G[v].size() ; ++i){ Edge & e = E[G[v][i]];Edge & rev = E[G[v][i]^1]; if(e.cap>0 && level[v]<level[e.to]){ int a = dfs(e.to,t,min(f,e.cap)); if(a>0){ e.cap-=a; rev.cap+=a; return a; } } } return 0; } int max_flow(int s,int t){ int flow = 0; for(;;){ bfs(s); if(level[t]<0)break; memset(cur,0,sizeof(cur)); int f; while ((f = dfs(s,t,INF))>0) { flow+=f; } } return flow; }}
对于上面的建边的方式,e的反向边就是e^1,这个可以自行枚举证明.
最大流最小切割定理
以下三个条件等价:
1.
2. 残存网络中没有增广路
3.
切割
最小割计算
计算网络中的两个割集
1.求最大流
2.从s开始dfs搜索.
这是由最大流最小割定理直接得出的,
Prof
二分图匹配
二分图的一个匹配是指二分图中的一些没有公共顶点的边集,匹配数就是边集的数目,最大匹配是指,使得这样的边集的数目最大.
算法
当作网络流来处理,将
不过由于是二分图我们可不必真的这样实现
Code
int V;std::vector<int> G[MAX_V];bool used[MAX_V];int match[MAX_V];bool dfs(int u){ used[u] = true; for(int i=0 ; i<G[u].size() ; ++i){ int v = G[u][i];int w = match[v]; if(w<0 || !used[w] && dfs(w)){ match[u] = v;match[v] = u; return true; } } return false;}int bipartite_match(){ int res = 0; memset(match,-1,sizeof(match)); for(int i = 1 ; i<=V ; ++i){ if(match[i]<0){ memset(used,false,sizeof(used)); if(dfs(i))res++; } } return res;}void add_edge(int u,int v){ G[u].push_back(v); G[v].push_back(u);}
最小费用流
在概念上最小费用流只是在最大流的边上在附加一个费用,即求出从源点到汇点的给定流量的最小费用.
算法
先从源点找一条到汇点的最短路,然后沿着最短路增广.建图的时候将反向边的费用设为-cost.(退流退费用)
Code
struct Edge{ int from,to,cap,cost; Edge(int f,int t,int c,int co):from(f),to(t),cap(c),cost(co){}};std::vector<Edge> E;std::vector<int> G[MAX_V];void add_edge(int u,int v,int cap,int cost){ E.push_back(Edge(u,v,cap,cost));G[u].push_back(E.size()-1); E.push_back(Edge(v,u,0,-cost)) ;G[v].push_back(E.size()-1);}struct MCMF{ int V; int dist[MAX_V]; int pre_E[MAX_V];//最短路径弧 bool inq[MAX_V];//spfa判断 //未判断负圈 void spfa(int s){ memset(dist,INF,sizeof(dist)); memset(inq,false,sizeof(inq)); queue<int> Q; Q.push(s); dist[s] = 0; inq[s] = true; pre_E[s] = -1; while(!Q.empty()) { int u = Q.front();Q.pop(); inq[u] = false; for(int i=0 ; i<G[u].size() ; ++i){ Edge &e = E[G[u][i]]; if(e.cap>0&&dist[e.to]>dist[u]+e.cost){ dist[e.to] = dist[u]+e.cost; pre_E[e.to] = G[u][i]; if(!inq[e.to]){Q.push(e.to);inq[e.to] = true;} } } } } int min_cost_flow(int s,int t,int f){ int res = 0; while (f>0) { spfa(s); if(dist[t]==INF)return break;//不能增广 //沿着最短路增广 int d = f; for(int i = pre_E[t] ; i!=-1 ;i = pre_E[E[i].from])d = min(d,E[i].cap); f-=d; res+=d*dist[t]; for(int i = pre_E[t] ; i!=-1 ;i = pre_E[E[i].from]){ E[i].cap-=d; E[i^1].cap+=d; } } return res; }};
负圈
如果有负圈,很显然,沿着负圈走费用会更少,而且沿着圈走是永远满足条件的
习题
以下习题代码网址
https://vjudge.net/contest/150004#overview
poj 3041 Asteroids
二分图匹配
最小顶点覆盖问题,二分图的最小顶点覆盖等于其最大匹配.行标与列标作为其顶点,小行星作为边链接.
poj 3057 Evacuation
二分图匹配
以每一个时刻对应的门与人为顶点建图,顺次建立,直到全部人匹配完,计算时间。
poj 3281 Dining
匹配问题网络流
匹配问题的网络流,不过一定要注意拆牛.一一对应。
poj 3469 Dual Core CPU
最小割
poj 2135 Farm Tour
最小费用流
poj 2175 Evacuation Plan
最小费用流,不过注意题意,并不需要求出,只需找到最优解,也就是沿着负圈增广一次即可.
poj 3686 The Windy’s
最小费用流
建图需分析仔细. 代码见上面的网址
poj 3680 Intervals
最小费用流
难在建图分析.
- 网络流题目总结
- 网络流【复习+总结】
- 网络流算法总结
- 网络流初步总结
- 网络流 构造总结
- poj 网络流 总结
- 网络流学习总结
- 网络流总结
- 【网络流】总结
- 网络流初步总结
- 【图论】网络流总结
- 网络流题目总结
- 网络流例题总结
- 网络流总结
- 网络流建模总结
- 网络流总结
- 网络流总结篇
- 网络流总结
- 数据结构-字符串匹配kmp模板
- 蓝桥杯 合并石子 DP+四边形不等式优化
- Android黑名单电话挂断(AIDL)
- linux下部署多个tomcat的方法
- Base58UUID生成
- 网络流总结
- SQL语句中----删除表数据drop、truncate和delete的用法
- Cocos2d-x内存管理——读我所理解的cocos2d-x整理
- JavaScript高级程序设计读书笔记(第六章)(一)
- 各种居中的方式
- CoreOS安装到硬盘
- 对一个文件中的指定信息进行过滤输出结果
- Nodejs 部署到阿里云全过程
- [C#]Array.Sort()排序的原理