最小费用最大流算法:
以费用作为权值,求出最小费用链,然后在这条链上求得一个最小流量,直到找不到费用链。求最小费用链也就相当于求 src−>des 的最短路径。使用 spfa+EK 算法。得到 MCMF 算法
代码:
#define MIN(a,b) ((a)>(b)? (b):(a))
using namespace std;
const int INF=0x3f3f3f3f;
const int SIZE=1000+5;
const int MAX_E=10000*4+100;
typedef struct tagNode{
int to,cap,cost,id;
tagNode(){}
tagNode(int to,int cap,int cost,int id):
to(to),cap(cap),cost(cost),id(id){}
}Node;
vector<Node> e[MAX_E];
int pre[SIZE];
int src,des,n,m;
int dis[SIZE];
bool used[SIZE];
void addedge(int from,int to,int cap,int cost)
{
int id_1=e[from].size();
int id_2=e[to].size();
e[from].push_back(Node(to,cap,cost,id_2));
e[to].push_back(Node(from,0,-cost,id_1));
}
bool spfa(int src,int des)
{
queue<int> que;
memset(used,false,sizeof(used));
for(int i=0;i<=SIZE;i++)
dis[i]=INF;
dis[src]=0;
que.push(src);
used[src]=true;
while(!que.empty()){
int v=que.front();
used[v]=false;
que.pop();
for(int i=0;i<e[v].size();i++){
int y=e[v].at(i).to;
if(e[v].at(i).cap>0&&dis[y]>dis[v]+e[v].at(i).cost){
dis[y]=dis[v]+e[v].at(i).cost;
pre[y]=e[v].at(i).id;
if(!used[y])
used[y]=true,
que.push(y);
}
}
}
return dis[des]<INF;
}
int MCMF(int src,int des)
{
int sum=0;
while(spfa(src,des)){
int minflow=INF,i;
for(i=des;i!=src;i=e[i].at(pre[i]).to)
minflow=MIN(minflow,e[e[i].at(pre[i]).to].at(e[i].at(pre[i]).id).cap);
for(i=des;i!=src;i=e[i].at(pre[i]).to)
e[e[i].at(pre[i]).to].at(e[i].at(pre[i]).id).cap-=minflow,
e[i].at(pre[i]).cap+=minflow;
sum+=dis[des]*minflow;
}
return sum;
}