zoukankan      html  css  js  c++  java
  • HDU 5644 (费用流)

    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
    ",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
    ",minC); else  printf("No solution
    ");
     96 
     97 }
     98 
     99 int main(){
    100     scanf("%d",&Que);
    101     while (Que--) {
    102         init();
    103         minCmaxF();
    104     }
    105 }
  • 相关阅读:
    mhWaveEdit 1.4.8
    FFmpeg — 屏幕录制器材
    GNOME 主题: Troll
    cGmail — 主动反省邮件
    最小化布置 Ubuntu
    GNOME Do — 疾速翻开法式和文件
    PyTone 一个控制台音乐播放器
    高恪守编辑器 VIM-把持篇(2)
    Cankiri:玲珑实用的屏幕录像机
    LiVES 0.9.6pre4
  • 原文地址:https://www.cnblogs.com/rpSebastian/p/5699529.html
Copyright © 2011-2022 走看看