逃跑

Description
    2009年12月5日,闷墩突然降临nsoi,于是nsoi的所有人只好举家搬迁,逃往其他教室上课。每个教室只允许一些人经过,只能留下一些学生(道理应该很简单)。所有的教室是用有向边连接起来的。问题是有多少人能够逃离闷墩的魔掌。



Input
    所有数均为(231-1)以内的自然数。
    第一行两个数n,m(1<n<=200),为全校教室的个数(包括nsoi)和nsoi的人数。这些教室编号为1到n,其中nsoi的编号为1。接下来(n-1)行,每行两个数,表示从2号教室开始允许经过的人数和能留下的人数,其中留下的人也必须先“经过”这个教室。
    接下来一行一个数k(1<=k<=40000),表示边的个数。然后k行,每行两个数a,b表示a号教室到b号教室是用有向边连通的。



Output
    一个自然数,为能逃离的人数。



Sample Input
4 20
10 5
20 5
10 10
3
1 2 
1 3
2 4 



Sample Output
15

还是利用拆点的思路吧 , 反正就是讲房间拆成两个点,这么乱搞 。

  1 #include <iostream>
  2 #include <cstdlib>
  3 #include <cstring>
  4 #include <cstdio>
  5 #include <queue>
  6 using namespace std ;
  7 const int inf = 1 << 30 , maxn = 40000 + 401  , N = 400 + 11;
  8 
  9 int  n , m , s , t , k;
 10 int sum[N][2] , head[N] , cnt , dis[N]  , cur[N];
 11 struct id
 12 {
 13     int nxt , to , vi ;
 14 } edge[maxn<<2] ;
 15 queue < int > Q ;
 16 
 17 
 18 inline void Init( )
 19 {
 20     freopen( "NSOOJ10734.in" , "r" , stdin ) ;
 21     freopen( "NSOOJ10734.out" , "w" , stdout ) ;
 22 }
 23 
 24 
 25 int read( )
 26 {
 27     char ch = getchar( ) ; int k = 1 , ret = 0 ;
 28     while( ch < '0' || ch > '9' ) { if( ch == '-' ) k = -1 ; ch = getchar( ) ;  }
 29     while( ch >= '0' && ch <='9' ) ret = ret * 10 + ch - '0' , ch = getchar( ) ;
 30     return ret * k ;
 31 }
 32 
 33 
 34 void add( int u , int v , int vi )
 35 {
 36     edge[++cnt].to = v , edge[cnt].vi = vi ;
 37     edge[cnt].nxt = head[u] , head[u] = cnt ;
 38 }  
 39 
 40 void input( )
 41 {
 42     n = read( ) , m = read( ) ; cnt = -1 ;
 43     s = n + 1 , t = 402 ; memset( head , -1 , sizeof(head) ) ;
 44     for( int x = 2 ; x <= n ; ++x )
 45     {
 46         sum[x][0] = read( ) , sum[x][1] = read( ) ;
 47         add( x , x + n, sum[x][0] ) ;
 48         add( x + n , x , 0 ) ;
 49         add( x+n , t , sum[x][1] ) ;
 50         add( t , x+n , 0 ) ;
 51     }
 52     k = read( ) ; int a , b ;    
 53     for( int i = 1 ; i <= k ; i++ )
 54     {
 55         a = read( ) , b = read( ) ;
 56         add( a + n , b , inf ) ;
 57         add( b , a + n , 0 ) ;
 58     }
 59 }
 60 
 61 
 62 bool bfs( ) 
 63 {
 64     memset( dis , -1 , sizeof(dis) ) ;
 65     dis[s] = 0 ; Q.push( s ) ;
 66     while( !Q.empty( ) )
 67     {
 68         int u = Q.front( ) ; Q.pop( ) ;
 69         for( int i = head[u] ; ~i ; i = edge[i].nxt )
 70         {
 71             int v = edge[i].to ;
 72             if( dis[v] < 0 && edge[i].vi > 0 )
 73             {
 74                 dis[v] = dis[u] + 1 ;
 75                 Q.push( v ) ;
 76             }
 77         }
 78     }
 79 //    cout<<endl;
 80     return dis[t] > 0 ;
 81 }
 82 
 83 
 84 long long int dfs( int u , long long int tmp )
 85 {
 86     if( u == t ) return tmp ;
 87     long long int an = 0ll , cost = 0ll ;
 88     for( int i = cur[u] ; ~i ; i = edge[i].nxt )
 89     {
 90         int  v = edge[i].to ;
 91         if( dis[v] != dis[u] + 1 ) continue ;
 92         an = dfs( v , min( tmp - cost , (long long )edge[i].vi ) ) ;
 93         edge[i].vi -= an , edge[i^1].vi += an ; cost += an;
 94         if( edge[i].vi ) cur[u] = i ; 
 95         if( cost == tmp ) return cost ;
 96     }
 97     if( !cost ) dis[u] = -1;
 98     return cost ;
 99 }
100 
101 void sov( )
102 {
103     long long int ans = 0 ;
104     while( bfs( ) ) 
105     {
106         for( int x = 1 ; x <= n<<1 ; ++x ) cur[x] = head[x] ;
107         head[s] = cur[s] ;
108         ans += dfs( s , (long long )inf ) ;
109     }
110     printf( "%d" , min( ans , (long long)m ) ) ;
111     return ;
112 }
113 
114 
115 int main( )
116 {
117 //    Init( ) ;
118     input( ) ;
119     sov( ) ;
120 //    fclose( stdin ) ;
121 //    fclose( stdout ) ;
122     return 0 ;
123 }
原文地址:https://www.cnblogs.com/Ateisti/p/5930449.html