#include <cstdio>
#include <iostream>
#include <cstring>
#include <vector>
using namespace std;
struct edge {
int to; //要到的点
int cap; //容量
int cost; //单位费用
int rev; //反向边
};
int V; //顶点数
vector<edge> G[MAXV]; //图的邻接表
int dis[MAXV]; //最短距离
int prevv[MAXV], preve[MAXV]; //最短路中的前驱节点和对应的边
//添加边
void add_edge(int from, int to, int cap, int cost) {
G[from].push_back((edge){to, cap, cost, G[to].size()}); //正向边
G[to].push_back((edge){from, 0, -cost, G[from].size() - 1}); //反向边
}
//求s到t流量为f的最小费用流
//如果不能再增广则返回-1
int min_cost_flow(int s, int t, int f) {
int res = 0;
while(f > 0) {
//利用Bellman-Ford算法求s到t的最短路
fill(dis, dis + V, INF);
dis[s] = 0;
bool update = true;
while(update) {
update = false;
for(int v = 0; v < V; ++v) {
if(dis[v] == INF)
continue;
for(int i = 0; i < G[v].size(); ++i) {
edge& e = G[v][i];
if(e.cap > 0 && dis[e.to] > dis[v] + e.cost) {
dis[e.to] = dis[v] + e.cost;
prevv[e.to] = v;
preve[e.to] = i;
update = true;
}
}
}
}
if(dis[t] == INF) //不能再增广了
return -1;
//沿s到t的最短路尽量增广
int d = f;
for(int v = t; v != s; v = prevv[v])
d = min(d, G[prevv[v]][preve[v]].cap);
f -= d;
res += d * dis[t];
for(int v = t; v != s; v = prevv[v]) {
edge& e = G[prevv[v]][preve[v]];
e.cap -= d;
//cost += d * e.cost;???????????????
G[v][e.rev].cap += d;
}
}
return res;
}
min_cost_flow
最新推荐文章于 2021-08-25 22:28:24 发布