志愿者招募

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了志愿者招募相关的知识,希望对你有一定的参考价值。

申奥成功后,布布经过不懈努力,终于成为奥组委下属公司人力资源部门的主管。布布刚上任就遇到了一个难题:为即将启动的奥运新项目招募一批短期志愿者。经过估算,这个项目需要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 }

 

以上是关于志愿者招募的主要内容,如果未能解决你的问题,请参考以下文章

志愿者招募

人工智能/云原生/数据科学/计算等方向内容整理志愿者招募了!

[NOI2008]志愿者招募

NOI2008志愿者招募

bzoj 1061: [Noi2008]志愿者招募

bzoj1061 [Noi2008]志愿者招募