/**
Edmonds-Karp算法是最简单的网络流算法,当然也比较慢复杂度为O(V*E^2)
编写简单而且很好理解。。后面还会贴最快的dinic 算法
复杂度为O(E*V^2) ( E为边数,V为点数)
网络流是个大学科,实在变化莫测,各种建图技巧,可以说竞赛考网络流
90%考建图,图建好了,直接套模板即可
这里只是简单的网络流模板而已
真正的学问是把实际问题转换为网络流问题
百度百科里这样描述网络流:
网络流 network flows网络流的理论和应用在不断发展,出现了具有增益的流、
多终端流、多商品流以及网络流的分解与合成等新课题。网络流的应用已遍及
通讯、运输、电力、工程规划、任务分派、设备更新以及计算机辅助设计等众多领域。
据我所知:甚至炒股问题也可以转换为网络流来搞
由于我也只是能看懂模板套模板而已,真正对流的理解甚微,所以就不多说了,
网络流在竞赛中很常见,属于重点内容,图中的一大分支,要引起足够的重视
*/
//由于我是用手敲的,只做参考,还请自行严格测试
const int inf = 0x3f3f3f3f;
const int M = 100; // 结点数
int map[M][M], ans, n; //ans 为最大流, n为节点个数
int pre[M], que[M], vis[M];
bool bfs(int s, int t) { //源点为s, 汇点为t
int head=0, tail=1;
memset(vis, 0, sizeof(vis));
que[0] = s; //加入源点
vis[s] = true;
while (tail > head) {
int u = que[head++];
for (int i=0; i<=n; i++) {
if (!vis[i] && map[u][i]) {
pre[i] = u; //前驱节点
if (i == t) //到达汇点
return true;
que[tail++] = i;
vis[i] = true;
}
}
}
return false;
}
void end(int s, int t) {
int i, sum = inf;
for (i=t; i!=s; i=pre[i])
sum = min(sum, map[pre[i]][i]);
for (i=t; i!=s; i=pre[i]) {
map[pre[i]][i] -= sum;
map[i][pre[i]] += sum;
}
ans += sum;
}
void EK(int s, int t) { //调用EK()即可,nv 为节点总数
while (bfs(int s, int t))
end(int s, int t);
}
/**
注意:
1、网络流问题属于有向图问题,可是我见过无向图的题目,
直接按无向图添边即可,如果不行就用链接表存边,后面会贴,
不过如果遇到最小费的无向图问题就必须用链接表了
2、如有多个源点汇点,一般用0做源点,n+1做汇点,添无限容量边
3、map[][] 数组只能用一次, ans赋初值为0
4、最大流等于最小割,网络流还可以解决二分图匹配问题
上面模板为依然空间的模板,也是最好理解的一个模板,
依然的代码风格和我很类似,所以好多东西都抄袭他的,嘿嘿
练习:POJ 1149 3281 1273 1459
*/
收藏于 2011-11-20
来自于百度空间
EK算法(连接矩阵)
最新推荐文章于 2021-03-20 18:02:40 发布