首页 > 代码库 > 志愿者招募

志愿者招募

申奥成功后,布布经过不懈努力,终于成为奥组委下属公司人力资源部门的主管。布布刚上任就遇到了一个难题:为即将启动的奥运新项目招募一批短期志愿者。经过估算,这个项目需要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\n" , ans ) ;120 }121 122 123 int main( )124 {125 //    Init( ) ; 126     input( ) ;127     zkw( ) ;128 //    fclose( stdin ) ;129 //    fclose( stdout ) ;130     return 0 ;131 }

 

志愿者招募