POJ 2396 有源汇的上下界可行流(好题)

(P.S.   POJ终于300题了,弱菜啊!!!)

题目链接: http://poj.org/problem?id=2396

题目大意:

  给定一个矩阵每行,每列的和,和各个元素的限制条件(>, =, <),求出一个满足这各种限制的矩阵。 

分析;

  我做了前面两道sgu的入门题,发现看这题的解题报告就很好懂了,其实原理方面我还是没有lin神那么理解得透彻。

  http://hi.baidu.com/zfy0701/blog/item/6449d82a64e15e3e5343c1ba.html

  http://blog.csdn.net/water_glass/article/details/6823741

注意:

  1、源S,汇T, 附加源ST(X), 附加汇ED(Y),将有源汇的转换为无源汇的应该是在添加了附加源汇之后再连一条T->S的容量为无穷大的边。

  2、这题我错了一天啊,究其原因非常神奇把input数据的处理随便改改就神奇地过了,也就是当输入x  y  =  t 时候,判断是否有错误的代码应该是:

    if( x>c[u][v] || x<l[u][v] ) Flag= 0;就足够了,而我自己多加了一句话就wa到底了(具体见下面的代码吧),这不是说明即使一个题你会算法,可以说什么都会照样有你在某在状态下ac不了的题么?

代码:

poj2396
  1 /*2396    Accepted    924K    141MS    C++    3650B    2012-06-18 21:53:56*/
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <cmath>
  5 #include <iostream>
  6 #include <algorithm>
  7 #include <vector>
  8 using namespace std;
  9 
 10 #define mpair make_pair
 11 #define pii pair<int,int>
 12 #define MM(a,b) memset(a,b,sizeof(a));
 13 typedef long long lld;
 14 typedef unsigned long long u64;
 15 template<class T> bool up_max(T& a,const T& b){return b>a? a=b,1 : 0;}
 16 template<class T> bool up_min(T& a,const T& b){return b<a? a=b,1 : 0;}
 17 #define maxn 240
 18 const int inf= 2100000000;
 19 
 20 int n,m,N;
 21 int ST, ED;
 22 int g[maxn][maxn];
 23 int c[maxn][maxn], l[maxn][maxn];
 24 
 25 bool Flag;
 26 
 27 void change(int u,int v,char ch,int x){
 28     if( '=' == ch ){
 29         /// if( c[u][v]==l[u][v] ) Flag= 0;  // if have this code, it gets Wrong Answer!!!
 30         if( x>c[u][v] || x<l[u][v] ) Flag= 0;
 31         c[u][v]= l[u][v]= x;
 32     }
 33     else if( '<' == ch ){
 34         up_min( c[u][v], x-1 );
 35         if( c[u][v] < l[u][v] ) Flag= 0;
 36     }
 37     else if( '>' == ch ){
 38         up_max( l[u][v], x+1 );
 39         if( c[u][v] < l[u][v] ) Flag= 0;
 40     }
 41 }
 42 
 43 void Read(){
 44     char ch;
 45     int i,j,u,v,x,t;
 46     cin>>n>>m;
 47     N= n+m+1;
 48     MM( c, 0 );
 49     MM( l, 0 );
 50     for(i=1;i<=n;++i){
 51         scanf("%d", &t);
 52         c[0][i]= l[0][i]= t;
 53     }
 54     for(i=1;i<=m;++i){
 55         scanf("%d", &t);
 56         c[i+n][N]= l[i+n][N]= t;
 57     }
 58     for(i=1;i<=n;++i)for(j=1;j<=m;++j){ c[i][j+n]= inf; l[i][j+n]= 0; }
 59     cin>>t;
 60     while( t-- ){
 61         scanf("%d %d %c %d", &u, &v, &ch, &x );
 62         if( 0==u && 0==v ){
 63             for(i=1;i<=n;++i) for(j=1;j<=m;++j) change( i, j+n, ch, x );
 64         }
 65         else if( 0==u ){
 66             for(i=1;i<=n;++i) change( i, v+n, ch, x );
 67         }
 68         else if( 0==v ){
 69             for(i=1;i<=m;++i) change( u, i+n, ch, x );
 70         }
 71         else change( u, v+n, ch, x );
 72     }
 73 }
 74 
 75 int build_graph(){
 76     int sum= 0;
 77     ST= N+1, ED= N+2;
 78     MM( g, 0 );
 79     for(int i=0;i<=N;++i){
 80         int t= 0;
 81         for(int j=0;j<=N;++j){
 82             t+= l[j][i]-l[i][j];
 83             g[i][j]= c[i][j]-l[i][j];
 84         }
 85         if(t>0) sum+= g[ST][i]= t; /// t>0!!!;
 86         else g[i][ED]= -t;
 87     }
 88     g[N][0]= inf; ///!!!
 89     return sum;
 90 }
 91 
 92 bool vis[maxn];
 93 int que[maxn], pre[maxn];
 94 bool bfs(){
 95     MM( vis, 0 );
 96     int head=0, tail=0;
 97     que[tail++]= ST;
 98     vis[ST]= 1;
 99     while( head<tail ){
100         int u= que[head++];
101         for(int v=0;v<=ED;++v){
102             if( g[u][v]>0 && !vis[v] ){
103                 pre[v]= u;
104                 if( v==ED ) return 1;
105                 que[tail++]= v;
106                 vis[v]= 1;
107             }
108         }
109     }
110     return 0;
111 }
112 
113 int Edmond_karp(){
114     int ret= 0;
115     while( bfs() ){
116         int t= inf;
117         for(int i=ED;i!=ST;i=pre[i])
118             up_min( t, g[pre[i]][i] );
119         ret+= t;
120         for(int i=ED;i!=ST;i=pre[i]){
121             g[pre[i]][i]-= t;
122             g[i][pre[i]]+= t;
123         }
124     }
125     return ret;
126 }
127 
128 int main()
129 {
130     //freopen("poj2396.in","r",stdin);
131     int Cas;
132     cin>>Cas;
133     while( Cas-- ){
134         Flag= 1;
135         Read();
136         if( !Flag ){
137             puts("IMPOSSIBLE");
138             if( Cas>0 ) puts("");
139             continue;
140         }
141 
142         int sum= build_graph();
143         int ret= Edmond_karp();
144         if( ret<sum ) puts("IMPOSSIBLE");
145         else{
146             for(int i=1;i<=n;++i)
147                 for(int j=1;j<=m;++j)
148                     //printf("%d%c", c[i][j+n]-g[i][j+n], j==m ? '\n' : ' ' );
149                     printf("%d%c", g[j+n][i]+l[i][j+n], j==m ? '\n' : ' ' );
150         }
151         if( Cas>0 ) puts("");
152     }
153 }
一毛原创作品,转载请注明出处。
原文地址:https://www.cnblogs.com/yimao/p/2554067.html