ホームに戻る
最小費用流問題(ダイクストラ)

// フローを流す場合の最小コストを求める。
// エッジには容量とコストを定める。
// コストは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;
}

inserted by FC2 system