bzoj 2406 二分+有源有汇上下界网络流可行流判定
弱爆了,典型的行列建模方式,居然想不到,题做少了,总结少了。。。。。。
二分答案mid
s----------------------->i行----------------------->j列----------------------------->t
[si-mid,si+mid] [L,R] [s[j]-mid,s[j]+mid]
即对每一行建一个点,每一列建一个点,用边来表示某一行某一列上的东西.
这种建模方式一般要整体考虑行或列的某些信息.
1 /************************************************************** 2 Problem: 2406 3 User: idy002 4 Language: C++ 5 Result: Accepted 6 Time:396 ms 7 Memory:4576 kb 8 ****************************************************************/ 9 10 #include <cstdio> 11 #include <cstring> 12 #define min(a,b) ((a)<(b)?(a):(b)) 13 #define oo 0x3f3f3f3f 14 #define N 510 15 #define S 100010 16 17 struct Dinic { 18 int n, src, dst; 19 int head[N], dest[S], flow[S], next[S], etot; 20 int dep[N], cur[N], qu[N], bg, ed; 21 22 void init( int n, int src, int dst ) { 23 memset( head, -1, sizeof(head) ); 24 etot = 0; 25 this->n = n; 26 this->src = src; 27 this->dst = dst; 28 } 29 void adde( int u, int v, int f ) { 30 // fprintf( stderr, "Dinic::adde( %d %d %d )\n", u, v, f ); 31 next[etot]=head[u]; flow[etot]=f; dest[etot]=v; head[u]=etot++; 32 next[etot]=head[v]; flow[etot]=0; dest[etot]=u; head[v]=etot++; 33 } 34 bool bfs() { 35 memset( dep, 0, sizeof(dep) ); 36 qu[bg=ed=1] = src; 37 dep[src] = 1; 38 while( bg<=ed ) { 39 int u=qu[bg++]; 40 for( int t=head[u]; ~t; t=next[t] ) { 41 int v=dest[t], f=flow[t]; 42 if( f && !dep[v] ) { 43 dep[v] = dep[u]+1; 44 qu[++ed] = v; 45 } 46 } 47 } 48 return dep[dst]; 49 } 50 int dfs( int u, int a ) { 51 if( u==dst || a==0 ) return a; 52 int remain=a, past=0, na; 53 for( int &t=cur[u]; ~t; t=next[t] ) { 54 int v=dest[t], &f=flow[t], &vf=flow[t^1]; 55 if( f && dep[v]==dep[u]+1 && (na=dfs(v,min(remain,f))) ) { 56 f -= na; 57 vf += na; 58 remain -= na; 59 past += na; 60 if( !remain ) break; 61 } 62 } 63 return past; 64 } 65 int maxflow() { 66 int f = 0; 67 while( bfs() ) { 68 for( int u=1; u<=n; u++ ) cur[u]=head[u]; 69 f += dfs( src, oo ); 70 } 71 // fprintf( stderr, "maxflow() = %d\n", f ); 72 return f; 73 } 74 }; 75 struct TopBot { 76 int n; 77 int head[N], dest[S], top[S], bot[S], next[S], etot; 78 int sin[N], sout[N]; 79 Dinic D; 80 void init( int n ) { 81 this->n = n; 82 etot = 0; 83 memset( head, 0, sizeof(head) ); 84 memset( sin, 0, sizeof(sin) ); 85 memset( sout, 0, sizeof(sout) ); 86 } 87 void adde( int u, int v, int t, int b ) { 88 // fprintf( stderr, "TopBot::adde( %d %d [%d,%d] )\n", u, v, b, t ); 89 etot++; 90 dest[etot] = v; 91 top[etot] = t; 92 bot[etot] = b; 93 next[etot] = head[u]; 94 head[u] = etot; 95 sin[v] += b; 96 sout[u] += b; 97 } 98 bool ok() { 99 int src=n+1, dst=n+2; 100 D.init( n+2, src, dst ); 101 for( int u=1; u<=n; u++ ) 102 for( int t=head[u]; t; t=next[t] ) { 103 int v=dest[t]; 104 D.adde( u, v, top[t]-bot[t] ); 105 } 106 int sumf = 0; 107 for( int u=1; u<=n; u++ ) { 108 if( sin[u]>sout[u] ) 109 D.adde( src, u, sin[u]-sout[u] ); 110 else if( sin[u]<sout[u] ) { 111 D.adde( u, dst, sout[u]-sin[u] ); 112 sumf += sout[u]-sin[u]; 113 } 114 } 115 // fprintf( stderr, "sumf=%d\n", sumf ); 116 return D.maxflow()==sumf; 117 } 118 }T; 119 120 int n, m; 121 int w[N][N], L, R; 122 int s[2][N]; 123 124 bool ok( int mid ) { 125 int src = n+m+1, dst = n+m+2; 126 int st=0, sb=0; 127 T.init(dst); 128 for( int i=1; i<=n; i++ ) { 129 int t=s[0][i]+mid, b=s[0][i]-mid; 130 b = b<0 ? 0 : b; 131 T.adde( src, i, t, b ); 132 st += t; 133 sb += b; 134 } 135 for( int i=1; i<=n; i++ ) 136 for( int j=1; j<=m; j++ ) 137 T.adde( i, n+j, R, L ); 138 for( int i=1; i<=m; i++ ) { 139 int t=s[1][i]+mid, b=s[1][i]-mid; 140 b = b<0 ? 0 : b; 141 T.adde( n+i, dst, t, b ); 142 } 143 T.adde( dst, src, st, sb ); 144 return T.ok(); 145 } 146 int main() { 147 scanf( "%d%d", &n, &m ); 148 for( int i=1; i<=n; i++ ) 149 for( int j=1; j<=m; j++ ) { 150 scanf( "%d", &w[i][j] ); 151 s[0][i] += w[i][j]; 152 s[1][j] += w[i][j]; 153 } 154 scanf( "%d%d", &L, &R ); 155 int lf=0, rg=200000; 156 while( lf<rg ) { 157 int mid=lf+((rg-lf)>>1); 158 if( ok(mid) ) rg=mid; 159 else lf=mid+1; 160 } 161 printf( "%d\n", lf ); 162 }