题目链接: http://poj.org/problem?id=1637
题目大意:
分析:
http://blog.163.com/zhoumhan_0351/blog/static/39954227200982051154725/
http://blog.csdn.net/niushuai666/article/details/6917777
http://www.cppblog.com/koson/archive/2007/12/21/39243.html
对于上面的建图,可以作如下改进法:对于每一条无向边e(i),涉及点j和点k, 则可以建立一条容量大小为1的边从v(j)流向v(k),从源点向v(j)添加一条容量为1的边。可以证明,改进的建图跟上面的前五步建图方法建立的图是等效的,但省略了e(i)更为简洁高效。
代码:
poj1637
1 /*1637 Accepted 376K 63MS C++ 2353B 2012-06-11 22:26:29*/ 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 210 18 const int inf = 2100000000; 19 20 int n,m; 21 int ST, ED; 22 int in[maxn], out[maxn], un[maxn]; 23 int g[maxn][maxn]; 24 25 bool vis[maxn]; 26 int que[maxn], pre[maxn]; 27 bool bfs(){ 28 MM( vis, 0 ); 29 int head= 0, tail= 0; 30 que[tail++]= ST; 31 vis[ST]= 1; 32 while( head<tail ){ 33 int u= que[head++]; 34 for(int v=1;v<=ED;++v){ 35 if( g[u][v] && !vis[v] ){ 36 pre[v]= u; 37 if( v==ED ) return 1; 38 que[tail++]= v; 39 vis[v]= 1; 40 } 41 } 42 } 43 return 0; 44 } 45 46 int Edmonds_karp(){ 47 int ret= 0; 48 while( bfs() ){ 49 int t= inf; 50 for(int i=ED;i!=ST;i= pre[i]) 51 up_min( t, g[pre[i]][i] ); 52 ret+= t; 53 for(int i=ED;i!=ST;i= pre[i]){ 54 g[ pre[i] ][i]-= t; 55 g[i][ pre[i] ]+= t; 56 } 57 } 58 return ret; 59 } 60 61 int main() 62 { 63 // freopen("poj1637.in","r",stdin); 64 int T; 65 cin>>T; 66 while( T-- ){ 67 cin>>n>>m; 68 int i,j,x,y,t; 69 MM( g, 0 ); 70 ST= 0, ED= n+1; 71 for(i=ST;i<=ED;++i) in[i]= out[i]= un[i]= 0; 72 while( m-- ){ 73 scanf("%d%d%d", &x, &y, &t); 74 if( 1==t ){ 75 ++out[x]; 76 ++in[y]; 77 } 78 else{ 79 ++un[x]; 80 ++un[y]; 81 ++g[ST][x]; /// 82 ++g[x][y]; /// 83 } 84 } 85 bool ok= 1; 86 int sum= 0; 87 for(i=1;i<=n;++i){ 88 int tot= in[i]+out[i]+un[i]; 89 if( tot&1 || in[i] > out[i] + un[i] || out[i] > in[i] + un[i] ){ 90 ok=0; break; 91 } 92 g[i][ED]+= tot / 2 - in[i]; 93 sum+= tot/2 - in[i]; 94 } 95 if( sum != Edmonds_karp() ) ok= 0; 96 97 if( !ok ) puts("impossible"); 98 else puts("possible"); 99 } 100 }