码迷,mamicode.com
首页 > 其他好文 > 详细

HDU 5644 (费用流)

时间:2016-07-23 22:48:47      阅读:268      评论:0      收藏:0      [点我收藏+]

标签:

Problem King‘s Pilots (HDU 5644)

题目大意

  举办一次持续n天的飞行表演,第i天需要Pi个飞行员。共有m种休假计划,每个飞行员表演1次后,需要休假Si天,并提供Ti报酬来进行下一次表演。刚开始拥有k个飞行员。也可以招募飞行员来进行表演(数量无限),需要提供报酬q,在p天后参加表演。询问使表演顺利进行的最少花费,若无法进行,输出No solution。

 

解题分析

  搬运官方题解:

  技术分享

  稍微解释一下:

  首先忽略Xi。Yi向T的流量表示第i天有多少人参加表演(第2条)。S向Y1的流量表示有多少人可以参加第一天的表演(第3条),并且可以累积到后几天来参加表演(第6条)。S向Yi的流量表示招募得到的飞行员(第4条)。

  接下来考虑Xi。Xi是用来解决休假问题的。Xi向Yj的流量表示到第i天已完成表演的的飞行员休假后从第j天开始可参加表演(第7条)。S向Xi的流量保证了休假的飞行员一定是已参加过表演的(第1条),并且开始休假的时间可以是任意的(第5条)。

 

  好厉害!好强!

参考程序

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <algorithm>
  4 #include <queue>
  5 using namespace std;
  6 
  7 #define V 1008
  8 #define E 1000008
  9 #define INF 200000000
 10 int n,m,k,S,T,p,q,Que,num;
 11 int ss[V],tt[V],P[V];
 12 
 13 int pd[V],dis[V],pre[V];
 14 struct line{
 15     int u,v,c,w,nt;
 16 }eg[E];
 17 int lt[V],sum;
 18 
 19 void adt(int u,int v,int c,int w) {
 20     eg[++sum].u=u; eg[sum].v=v; eg[sum].c=c; 
 21     eg[sum].w=w; eg[sum].nt=lt[u]; lt[u]=sum;
 22 }
 23 
 24 void add(int u,int v,int c,int w) {
 25     adt(u,v,c,w); adt(v,u,0,-w);
 26    // printf("%d %d %d %d\n",u,v,c,w);
 27 }
 28 
 29 void init(){
 30 
 31     sum=1; num=0;
 32     memset(lt,0,sizeof(lt));
 33     scanf("%d%d",&n,&k);
 34     for (int i=1;i<=n;i++) { scanf("%d",&P[i]); num+=P[i]; }
 35     scanf("%d%d%d",&m,&p,&q);
 36     for (int i=1;i<=m;i++) scanf("%d%d",&ss[i],&tt[i]);
 37 
 38     S=0; T=n*2+1;
 39     for (int i=1;i<=n;i++) add(S,i,P[i],0);
 40     for (int i=1;i<=n;i++) add(i+n,T,P[i],0);
 41     add(S,n+1,k,0);
 42     for (int i=1;i<=n;i++)
 43         if (i>=p) add(S,i+n,INF,q);
 44     for (int i=1;i<n;i++) add(i,i+1,INF,0);
 45     for (int i=n+1;i<n*2;i++) add(i,i+1,INF,0);
 46     for (int j=1;j<=m;j++)
 47         for (int i=1;i<=n;i++)
 48             if (i+tt[j]<=n)
 49                 add(i,i+tt[j]+n,INF,ss[j]);
 50     n=T;    
 51     
 52 }
 53 
 54 bool spfa() {
 55     queue <int> Q;
 56     for (int i=0;i<=n;i++) {
 57         dis[i]=INF;
 58         pd[i]=0;
 59         pre[i]=-1;
 60     }
 61     dis[S]=0; pd[S]=1; Q.push(S);
 62     while (!Q.empty()) {
 63         int u = Q.front();
 64         for (int i=lt[u];i;i=eg[i].nt) 
 65             if (eg[i].c>0) {
 66                 int v=eg[i].v;
 67                 if (dis[u]+eg[i].w<dis[v]) {
 68                     dis[v]=dis[u]+eg[i].w;
 69                     pre[v]=i;
 70                     if (!pd[v]) {
 71                         Q.push(v);
 72                         pd[v]=1;
 73                     }
 74                 }
 75             }
 76         pd[u]=0;
 77         Q.pop();
 78     }
 79     return dis[T]!=INF;
 80 }
 81 
 82 void minCmaxF(){
 83     int minC=0,maxF=0,flow;
 84     while (spfa()) {
 85         flow=INF;
 86         for (int i=pre[T];~i;i=pre[eg[i].u])
 87             flow=min(flow,eg[i].c);
 88         for (int i=pre[T];~i;i=pre[eg[i].u]) {
 89             eg[i].c-=flow;
 90             eg[i^1].c+=flow;
 91         }
 92         maxF+=flow;
 93         minC+=flow*dis[T];
 94     }
 95     if (maxF==num) printf("%d\n",minC); else  printf("No solution\n");
 96 
 97 }
 98 
 99 int main(){
100     scanf("%d",&Que);
101     while (Que--) {
102         init();
103         minCmaxF();
104     }
105 }

 

HDU 5644 (费用流)

标签:

原文地址:http://www.cnblogs.com/rpSebastian/p/5699529.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!