zoukankan      html  css  js  c++  java
  • 志愿者招募

    申奥成功后,布布经过不懈努力,终于成为奥组委下属公司人力资源部门的主管。布布刚上任就遇到了一个难题:为即将启动的奥运新项目招募一批短期志愿者。经过估算,这个项目需要N 天才能完成,其中第i 天至少需要Ai 个人。 布布通过了解得知,一共有M 类志愿者可以招募。其中第i 类可以从第Si 天工作到第Ti 天,招募费用是每人Ci 元。新官上任三把火,为了出色地完成自己的工作,布布希望用尽量少的费用招募足够的志愿者,但这并不是他的特长!于是布布找到了你,希望你帮他设计一种最优的招募方案。

    Input

    第一行包含两个整数N, M,表示完成项目的天数和可以招募的志愿者的种类。 接下来的一行中包含N 个非负整数,表示每天至少需要的志愿者人数。 接下来的M 行中每行包含三个整数Si, Ti, Ci,含义如上文所述。为了方便起见,我们可以认为每类志愿者的数量都是无限多的。

    Output

    仅包含一个整数,表示你所设计的最优方案的总费用。

    Sample Input

    3 3

    2 3 4

    1 2 2

    2 3 5

    3 3 2 
    Sample Output

    14 

    看到这道题就有一种套路感 ,qwq 。

    我们将原点和第一时刻 ,然后第一时刻与第二时刻 ,这样依次连边

    因为只有下界没有上界,所有容量连为inf-ai ,

    然后将si和ti+1直接连一条(inf , cost)的边。

    这是我想到的比较简单的做法 , 而某大神的做法我只能%%,

    附上链接:https://www.byvoid.com/blog/noi-2008-employee/#more-916

      1 #include <iostream>
      2 #include <cstdlib>
      3 #include <cstring>
      4 #include <cstdio>
      5 #include <queue>
      6 const int inf = 1 << 30 , maxn = 1000 + 11  ; 
      7 using namespace std ;//1061109567
      8 int m , n , head[maxn] ,  dis[maxn]  , s ,t ,ans , cnt ;
      9 bool mark[maxn] ;
     10 struct id
     11 {
     12     int to , nxt , val , vol ;
     13 }  edge[50012] ;
     14 queue< int > Q ;
     15 
     16 inline void Init ( )
     17 {
     18     freopen( "NSOOJ#10366.in" , "r" , stdin  ) ;
     19     freopen( "NSOOJ#10366.out" , "w" , stdout ) ;
     20 }
     21 
     22 int read( )
     23 {
     24     char ch = getchar( ) ; int k = 1 , ret = 0 ;
     25     while( ch < '0' || ch > '9' ) { if( ch == '-' ) k = -1 ; ch = getchar( ) ; }
     26     while( ch >= '0' && ch <= '9' ) ret = ret * 10 + ch - '0' , ch = getchar( ) ;
     27     return k * ret ;
     28 }
     29 
     30 void add( int u , int v , int va , int vo )
     31 {
     32     edge[++cnt].nxt = head[u] , edge[cnt].to = v ;
     33     edge[cnt].val = va , edge[cnt].vol = vo , head[u] = cnt ;
     34 }
     35 
     36 void input(  )
     37 {
     38     int n , m ; n = read( ) , m = read( ) ;
     39     s = 1 , t = n + 2  ;int  a ; cnt = -1;
     40     memset( head , -1 , sizeof(head) ) ;
     41     add( 1 , 2 , inf , 0 ) ; add( 2 , 1 , inf , 0 ) ;
     42     for( int x = 1 ; x <= n ; ++x )
     43     {
     44         a = read( ) ;
     45         add( x+1 , x+2 , inf - a , 0 ) ;
     46         add( x+2 , x+1 , 0 , 0 ) ;
     47     } 
     48     int i , j , k ;
     49     for( int x = 1 ; x <= m ; ++x )
     50     {
     51         i = read( ) , j = read( ) , k = read( ) ;
     52         add( i+1 , j+2 , inf , k ) ;
     53         add( j+2 , i+1 , 0 , 0-k ) ;
     54     }
     55 }
     56 
     57 bool spfa(  )
     58 {
     59     memset( mark , 0 , sizeof(mark) ) ;
     60     memset( dis , 127/2 , sizeof(dis) ) ;
     61     mark[t] = 1 ; dis[t] = 0 ;     Q.push( t ) ;
     62     while( !Q.empty( ) )
     63     {
     64         int u = Q.front( ) ; Q.pop( ) ;
     65         for( int i = head[u] ; ~i ; i = edge[i].nxt )
     66         {    
     67             
     68             int v = edge[i].to ;
     69             if( edge[i^1].val && dis[v] > dis[u] + edge[i^1].vol )
     70             {    
     71                 dis[v] = dis[u] + edge[i^1].vol ;
     72                 if( !mark[v] )
     73                 {
     74                     mark[v] = 1 ;
     75                     Q.push( v ) ;
     76                 }
     77             }
     78             
     79         }
     80         mark[u] = false ;
     81     } 
     82     return dis[s] != 1061109567 ;
     83 }
     84  
     85  
     86 int dfs( int u , int f )
     87 {
     88     mark[u] = true ;
     89     if( u == t ) return f ;
     90     int w , used = 0 ;
     91     for( int i = head[u] ; ~i ; i = edge[i].nxt )
     92     {
     93         int v = edge[i].to ;
     94         if( dis[v] == dis[u] - edge[i].vol && edge[i].val && !mark[v] )
     95         {
     96             w = f - used ;
     97             w = dfs( v , min( w , edge[i].val ) ) ;
     98             ans += w * edge[i].vol ;
     99             edge[i].val -= w , edge[i^1].val += w ; used += w ;
    100             if( used == f )  return used ;
    101         }
    102     }
    103     return used ;
    104 }
    105  
    106 
    107 void zkw(  )
    108 {
    109     int sum = 0 ;
    110     while( spfa( ) )
    111     {
    112         mark[t] = 1 ; 
    113         while( mark[t] )
    114         {
    115             memset( mark , 0 , sizeof(mark) ) ;
    116             sum = dfs( s , inf ) ;
    117         }
    118     }
    119     printf( "%d
    " , ans ) ;
    120 }
    121 
    122 
    123 int main( )
    124 {
    125 //    Init( ) ; 
    126     input( ) ;
    127     zkw( ) ;
    128 //    fclose( stdin ) ;
    129 //    fclose( stdout ) ;
    130     return 0 ;
    131 }
  • 相关阅读:
    vs code 编译python 输出到调试控制台
    vs code个性化设置
    IDEA 简拼输入
    微信小程序 audio组件 默认控件 无法隐藏/一直显示/改了controls=‘false’也没用2019/5/28
    win10的cortana搜索显示空白
    微信小程序tabbar不显示2019.04.06
    读《提问的智慧》有感
    CLion 控制台输出内容乱码问题的解决方法
    vs code C语言环境搭建
    利用python的爬虫技术爬去糗事百科的段子
  • 原文地址:https://www.cnblogs.com/Ateisti/p/5937318.html
Copyright © 2011-2022 走看看