码迷,mamicode.com
首页 > 其他好文 > 详细

bzoj 2406 二分+有源有汇上下界网络流可行流判定

时间:2015-06-03 21:17:35      阅读:325      评论:0      收藏:0      [点我收藏+]

标签:

 

弱爆了,典型的行列建模方式,居然想不到,题做少了,总结少了。。。。。。

二分答案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 }
View Code

 

bzoj 2406 二分+有源有汇上下界网络流可行流判定

标签:

原文地址:http://www.cnblogs.com/idy002/p/4550153.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!