[HDOJ 4807] Lunch Time [费用流]

来源:互联网 发布:淘宝 180px 编辑:程序博客网 时间:2024/05/15 07:10

一群小伙伴要从0号点走到n-1号点,整个图是有向图,每条边有最大流量,即单位时间内通过的小伙伴的最大值,每个小伙伴走过一条边的时间都是1,求最短需要多少时间可以让k个小伙伴都达到n-1号点。

费用流,所有边的费用都是1,每次SPFA后,若费用为t,新增流量f,即表示从t时刻开始,每个时刻都可以有额外的f个小伙伴到达。

注意k=0时特判。

#include <cstdio>#include <cstring>    const int MAXINT=(1<<30);    static const int N=2510;  static const int M=5000;  struct Node {  int fe,c,f,fromNode,curCost,fromEdge;  bool inque;  };  struct Edge {  int f,t,ne,c;  };  Node a[N];  Edge b[M*2];  int d[N];  int s,t,n,p,cost;  int m,k,ans,curf,curt;void arrive(int t,int p) {//printf("%d %d\n",t,p);if (k==0) return;if (curf!=0) {int tmp=k/curf+(k%curf!=0);if (curt+tmp<=t) {curt+=tmp;k=0;return;} else {tmp=t-curt;k-=tmp*curf;}}curf+=p;curt=t;}void clear(int nn,int ss,int tt) {  n=nn;s=ss;t=tt;  for (int i=0;i<n;i++) {  a[i].fe=-1;  a[i].f=0;  a[i].c=0;  }  p=0;  cost=0;  }  void putedge(int x,int y,int f,int c) { b[p].ne=a[x].fe;  b[p].t=y;  b[p].f=f;  b[p].c=c;  a[x].fe=p++;  b[p].ne=a[y].fe;  b[p].t=x;  b[p].f=0;  b[p].c=-c;  a[y].fe=p++;  }  bool spfa() {  int i,p,q,j;  for (i=0;i<n;i++) {  a[i].curCost=MAXINT;  a[i].fromNode=-1;  a[i].fromEdge=-1;  a[i].inque=false;  }  p=q=0;  d[q++]=s;  a[s].inque=true;  a[s].curCost=0;  while (p!=q) {  i=d[p];  for (j=a[i].fe;j!=-1;j=b[j].ne) {  if (b[j].f>0&&b[j].c+a[i].curCost<a[b[j].t].curCost) {  a[b[j].t].curCost=a[i].curCost+b[j].c;  a[b[j].t].fromNode=i;  a[b[j].t].fromEdge=j;  if (a[b[j].t].inque==false) {  a[b[j].t].inque=true;  d[q]=b[j].t;  q=(q+1)%N;  }  }  }  a[i].inque=false;  p=(p+1)%N;  }  if (a[t].curCost==MAXINT) return false;  p=MAXINT;  q=0;  for (i=t;i!=s;i=a[i].fromNode) {  d[q++]=i;  if (p>b[a[i].fromEdge].f) p=b[a[i].fromEdge].f;  }  j=0;  for (i=q-1;i>=0;i--) {  j+=b[a[d[i]].fromEdge].c*p;  b[a[d[i]].fromEdge].f-=p;  b[a[d[i]].fromEdge^1].f+=p;  a[d[i]].c+=j;  a[d[i]].f+=p;  }  arrive(a[t].curCost,p);return true;  }  void flow() {  int i;  a[s].f=MAXINT;  while (spfa()) ;  }  int main() {int i,x,y,z;while (scanf("%d%d%d",&n,&m,&k)!=EOF) {clear(n,0,n-1);for (i=0;i<m;i++) {scanf("%d%d%d",&x,&y,&z);putedge(x,y,z,1);}if (k==0) {printf("0\n");continue;}ans=0;curf=0;curt=0;flow();if (a[t].f==0) printf("No solution\n");else {if (k!=0) ans=curt+k/curf+(k%curf!=0);else ans=curt;printf("%d\n",ans-1);}}return 0;}


0 0