ホームに戻る
最小費用流問題(ダイクストラ)
// フローを流す場合の最小コストを求める。
// エッジには容量とコストを定める。
// コストは1容量あたりのコストになる。
// O(F|E|log|V|)もしくはO(F|V|^2|)
// MAX_Vは最大のノード数を書いておくこと。
// ae(from,to,capacity,cost) でエッジを張る。
// minCostFlow(from,to,volumes,nodes) 量を流す。volumesは流したい流量、nodesはノード数。
// もしすべて流れないのであれば -1 を返す。
#define MAX_V 100
#define INF 1000000000000000000LL
typedef pair<long long, long long> P;
struct edge{long long to, cap, cost, rev;};
vector<edge> G[MAX_V];
long long h[MAX_V];
long long dist[MAX_V];
long long prevv[MAX_V];
long long preve[MAX_V];
void ae(long long from, long long to, long long cap, long long cost){
G[from].push_back((edge){to, cap, cost, G[to].size()});
G[to].push_back((edge){from, 0, -cost, G[from].size() - 1});
}
long long minCostFlow(long long s, long long t, long long f, long long V){
long long res = 0;
memset(h,0,sizeof(h));
while(f > 0){
c1++;
priority_queue<P, vector<P>, greater<P> > que;
for(long long i = 0; i < V; i++){
dist[i] = INF;
}
dist[s] = 0;
que.push(P(0,s));
while(!que.empty()){
P p = que.top(); que.pop();
long long v = p.second;
if(dist[v] < p.first)continue;
for(long long i = 0; i < G[v].size(); i++){
c2++;
edge &e = G[v][i];
if(e.cap > 0 && dist[e.to] > dist[v] + e.cost + h[v] - h[e.to]){
dist[e.to] = dist[v] + e.cost + h[v] - h[e.to];
prevv[e.to] = v;
preve[e.to] = i;
que.push(P(dist[e.to], e.to));
}
}
}
if(dist[t] == INF){
return -1;
}
for(long long v = 0; v < V; v++){
h[v] += dist[v];
}
long long d = f;
for(long long v = t; v != s; v = prevv[v]){
d = min(d, G[prevv[v]][preve[v]].cap);
}
f -= d;
res += d * h[t];
for(long long v = t; v != s; v = prevv[v]){
edge &e = G[prevv[v]][preve[v]];
e.cap -= d;
G[v][e.rev].cap += d;
}
}
return res;
}
int main(){
ae(0,1,2,0);
ae(1,2,2,7);
cout << minCostFlow(0,2,2,3) << endl;
return 0;
}
最小費用流問題(ベルマンフォード)
// フローを流す場合の最小コストを求める。
// エッジには容量とコストを定める。
// コストは1容量あたりのコストになる。
// ベルマンフォードなので負のコストも可能。
// O(F|V||E|)
// ae(from,to,capacity,cost) でエッジを張る。
// minCostFlow(from,to,volumes,nodes) 量を流す。volumesは流したい流量、nodesはノード数。
// もしすべて流れないのであれば -1 を返す。
#define MAX_V 100
#define INF 1000000000000000000LL
struct edge{long long to, cap, cost, rev;};
vector<edge> G[MAX_V];
long long dist[MAX_V];
long long prevv[MAX_V];
long long preve[MAX_V];
void ae(long long from, long long to, long long cap, long long cost){
G[from].push_back((edge){to, cap, cost, G[to].size()});
G[to].push_back((edge){from, 0, -cost, G[from].size() - 1});
}
long long minCostFlow(long long s, long long t, long long f, long long V){
long long res = 0;
while(f > 0){
for(long long i = 0; i < V; i++){
dist[i] = INF;
}
dist[s] = 0;
long long flag = 1;
while(flag == 1){
flag = 0;
for(long long v = 0; v < V; v++){
if(dist[V] == INF)continue;
for(long long i = 0; i < G[v].size(); i++){
edge &e = G[v][i];
if(e.cap > 0 && dist[e.to] > dist[v] + e.cost){
dist[e.to] = dist[v] + e.cost;
prevv[e.to] = v;
preve[e.to] = i;
flag =1;
}
}
}
}
if(dist[t] == INF){
return -1;
}
long long d = f;
for(long long v = t; v != s; v = prevv[v]){
d = min(d, G[prevv[v]][preve[v]].cap);
}
f -= d;
res += d * dist[t];
for(long long v = t; v != s; v = prevv[v]){
edge &e = G[prevv[v]][preve[v]];
e.cap -= d;
G[v][e.rev].cap += d;
}
}
return res;
}
int main(){
ae(0,1,2,0);
ae(1,2,2,7);
cout << minCostFlow(0,2,2,3) << endl;
return 0;
}