最近在看 最大流问题,因为是第一次涉及到这种问题,以及第一次接触到这种类型的算法,所以刚开始一头雾水。
首先,这种问题概念比较多,残存网络,增广路径,最小割,流量对称,等。 其次,虽然有现成的方法解决,但是解决此方法的算法有多种,优化的算法也有很多。
刚开始看 Dinic 匈牙利算法,真心没看懂。。
现在我写了一份模板,是EK算法实现的。应该算最简单的一种实现方法了。我觉得,只要会熟练掌握一种方法,并且能够熟练运用,已经很好了。
#include <iostream>
#include <queue>
using namespace std;
#define MAXV 100
#define MAX 1<<29
int map[MAXV][MAXV]; //纪录残存网络的容量
int flow[MAXV]; //表示源点到该点还剩多少流量可用
int pre[MAXV]; //表示该节点的前驱节点,同时标记该节点是否在队列中
int n; //表示网络中的节点数目
queue<int>q;
int BFS(int src,int des){
int i;
while(!q.empty()){ //队列清空
q.pop();
}
memset(pre,-1,sizeof(pre)); //初始化前驱节点
pre[src] = 0;
flow[src] = MAX;
q.push(src);
while(!q.empty()){
int index = q.front();
q.pop();
if(index == des)
break;
for(i=1;i<=n;i++){
if(i!=src && pre[i]==-1 && map[index][i]>0){
pre[i] = index;
flow[i] = min(map[index][i],flow[index]);
q.push(i);
}
}
}
if(pre[des] == -1) //残余图中不存在增广路径
return -1;
else
return flow[des]; //一条路径中可增加的流量
}
int maxFlow(int src,int des){
int increasement = 0;
int sumflow = 0;
while((increasement = BFS(src,des))!=-1){
int k = des; //利用前驱寻找路径
while(k!=src){
int last = pre[k];
map[last][k] -= increasement; //正向边流量减少
map[k][last] += increasement; //反向边流量增加
k = last;
}
sumflow += increasement;
}
return sumflow;
}
为了更好的理解这个模板,我结合POJ 1459最大流问题,用此套模板实现一下。POJ 1459关键就是重建一个源点,一个汇点,将源点与所有点发电站相连,将汇点与所有的消费者相连,这样最大流 就是所要求的消费者最多可获得的电量。
#include <iostream>
#include <queue>
using namespace std;
#define MAXV 110
#define MAX 1<<29
int map[MAXV][MAXV];
int pre[MAXV];
int flow[MAXV];
int n;
queue<int>q;
int BFS(){ //src=0,des=n+1
int i;
memset(pre,-1,sizeof(pre));
while(!q.empty())
q.pop();
pre[0] = 0;
flow[0] = MAX;
q.push(0);
while(!q.empty()){
int index = q.front();
q.pop();
if(index == n+1)
break;
for(i=1;i<=n+1;i++){
if(map[index][i]&&pre[i]==-1){
pre[i] = index;
flow[i] = min(flow[index],map[index][i]);
q.push(i);
}
}
}
if(pre[n+1] == -1)
return -1;
else
return flow[n+1];
}
int maxFlow(){
int increasement = 0;
int sumflow = 0;
while((increasement = BFS())!=-1){
int k = n+1;
while(k!=0){
int last = pre[k];
map[last][k] -= increasement;
map[k][last] += increasement;
k = last;
}
sumflow += increasement;
}
return sumflow;
}
int main(){
int np,nc,m;
int i;
int u,v,value;
while(cin>>n>>np>>nc>>m){
char s;
memset(map,0,sizeof(map));
for(i=0;i<m;i++){
cin>>s>>u>>s>>v>>s>>value;
if(u!=v)
map[u+1][v+1] = value;
}
for(i=0;i<np;i++){
cin>>s>>u>>s>>value;
map[0][u+1] = value;
}
for(i=0;i<nc;i++){
cin>>s>>u>>s>>value;
map[u+1][n+1] = value;
}
cout<<maxFlow()<<endl;
}
return 0;
}