1088-School Excursion

問題概要

日本語なので略

解法

グラフを構築し,最小費用流をする.
基本的に流量はINFだが,同じ時刻に到着する列車については流量1の辺を張るようにする.

実装(C++)

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
#define REP(i,x)for(int i=0;i<x;i++)
struct E{int dst,cost,cap,rev;};
vector<E> G[100000];
int m[100],x[100][20],y[100][20],c[100][20],n,g,v;
void add_edge(int s,int d,int c,int f){
  G[s].push_back((E){d,c,f,G[d].size()});
  G[d].push_back((E){s,-c,0,G[s].size()-1});
}
void min_cost_flow(int s,int t,int f){
  typedef pair<int,int> P;
  int res=0,V=v,es=f;
  vector<int> prevv(V),preve(V);
  while(f>0){
    vector<int> dist(V,99999999);
    bool update=true;
    dist[s]=0;
    while(update){
      update=false;
      REP(v,V){
        if(dist[v]==99999999)continue;
        REP(i,G[v].size()){
          E &e=G[v][i];
          if(e.cap>0&&dist[e.dst]>dist[v]+e.cost){
            dist[e.dst]=dist[v]+e.cost;
            prevv[e.dst]=v;
            preve[e.dst]=i;
            update=true;
          }
        }
      }
    }
    if(dist[t]==99999999){
      cout<<es-f<<" "<<res<<endl;
      return;
    }
    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*dist[t];
    for(int v=t;v!=s;v=prevv[v]){
      E &e=G[prevv[v]][preve[v]];
      e.cap-=d;
      G[v][e.rev].cap+=d;
    }
  }
  cout<<es-f<<" "<<res<<endl;
  return;
}
int main(){
  for(;cin>>n,n;v=0){
    fill(G,G+10000,vector<E>());
    REP(i,n-1){
      cin>>m[i];
      REP(j,m[i])cin>>x[i][j]>>y[i][j]>>c[i][j];
    }
    cin>>g;
    REP(j,n-1){
      REP(i,m[j]){
        bool ok=1;
        REP(k,i){
          if(y[j][i]==y[j][k])ok=0;
        }
        if(!ok)continue;
        REP(k,m[j]){
          if(y[j][i]==y[j][k]){
            add_edge(v+k,v+m[j]+i,c[j][k],1);
          }
        }
        add_edge(v+m[j]+i,v+m[j]*2+i,0,1);
      }
      v+=m[j]*3;
    }
    v=m[0]*3;
    for(int j=1;j<n-1;j++){
      REP(p,m[j-1])REP(q,m[j]){
        if(y[j-1][p]<=x[j][q])
          add_edge(v-m[j-1]+p,v+q,0,9999);
      }
      v+=m[j]*3;
    }
    REP(i,m[0]){
      add_edge(v,i,0,9999);
    }
    REP(i,m[n-2]){
      add_edge(v-m[n-2]+i,v+1,0,9999);
    }
    v+=2;
    min_cost_flow(v-2,v-1,g);
  }
}