网络流:
(http://blog.youkuaiyun.com/mystery_guest/article/details/51910913)
答案是10,写完程序跑出来8,因为没有理解反向边。关于反向边,这篇文章说的非常好。
(http://blog.youkuaiyun.com/vonmax007/article/details/64921089)
//网络流:最大流问题,最小费用最大流是它的推广
//最大流:求出一个可行流。减去该流后再由残余网络求出可行流。最后合并可行流
//使用图的矩阵表示 .有向图
//Ford Fulkerson 算法的精华是反向边。它就是错误算法错误的根源。反向边的存在给了程序一个反悔的机会。
//起点和终点的反向边是无法利用的,而中间节点的反向边是可以利用的。
//图的矩阵表示表示起来非常方便。我们甚至无法区分正向边和反向边
//最大流的最小费问题:在选择路径时不再使用bfs算法,而使用基于费用的最短路径算法。路径叠加后即得到最大流的最小费
#include <iostream>
#include <iomanip>
#include <queue>
using namespace std;
int s[7][7] = {};
int end[7][7] = {};
int path[7] = {};//访问标志数组。因为只遍历一次,所以可以由该数组存储路径
queue<int> que;
void bfs(){
while(!que.empty()){
int a = que.front();
que.pop();
if(a == 6) break;
for(int i=1;i<=6;i++){
if(s[a][i] != 0 && path[i] == 0){
que.push(i);
path[i] = a;
}
}
}
}
int main(){
s[1][4] = 7;
s[1][2] = 6;
s[2][3] = 4;
s[2][5] = 4;
s[3][6] = 4;
s[4][5] = 2;
s[4][3] = 3;
s[5][6] = 8;
while(true){
while(!que.empty()){
que.pop();
}
for(int i=1;i<=6;i++){
path[i] = 0;
}
que.push(1);
path[1] = 1;
bfs();
if(path[6] == 0){
int value = 0;
for(int i=0;i<=6;i++){
value = value + end[i][6];
}
cout <<"最大流量:"<<value<<"\n";
for(int i=1;i<=6;i++){
for(int j=i;j<=6;j++){
if(end[i][j] != 0){
cout <<i<<"→"<<j<<" : "<<end[i][j]-end[j][i]<<"\n";
}
}
}
break;
} else{
int the = 6;
int last = path[6];
int value = s[last][6];
while(last != 1){
the = last;
last = path[last];
value = value <= s[last][the] ? value : s[last][the];
}
the = 6;
last = path[6];
while(the != 1){
s[last][the] = s[last][the] - value;
s[the][last] = s[the][last] + value;//反向边 .一句话解决问题。
end[last][the] = end[last][the] + value;
the = last;
last = path[the];
}
}
}
cout << "true";
return 0;
}