(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 }