题目链接: http://poj.org/problem?id=2516
题目大意及分析:
http://blog.csdn.net/lyy289065406/article/details/6742534
这个题解非常非常详细,我的构图和他反了下,本质一样。
这题KM的做法: http://blog.csdn.net/ChinaCzy/article/details/5813011
P.S. 这题我错了三天,三天来一直在搞这题,把网上一份和我的类似的代码找来改成我的风格,不断差错……
不觉得把时间这样浪费是一种对生命的亵渎吗?区域赛说近也近了,三天可以做多少事啊!
1、我过去习惯的spfa的写法都是错误的,以后一律使用循环队列,且用 if( head==maxn ) head= 0; 更快!本题边权非负,所以不需要开cnt[]来记录是否有负环,既然是循环队列那么必须要用 while( head != tail )来结束循环而不是习惯性地 head<tail;
2、所谓费用流,是: 费用*流量,我忘记这一点就错了很久……
3、一定记得反边的边权是正向边边权的相反数;
4、这题开始我一直想不通那个k个物品怎么办,后来是看了题解才知道他们确实是独立的,要分别做费用流,可是我明明会这种费用流,为什么会错这么久呢? 我实在是不知道错在哪里了。
代码:
poj2516
1 /*2516 Accepted 404K 266MS C++ 2635B 2012-06-22 14:08:10*/ 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 110 18 const int inf= 2100000000; 19 20 int n,m,k; 21 int ST, ED; 22 int c[maxn][maxn], f[maxn][maxn]; 23 24 bool vis[maxn]; 25 int que[maxn+10], dis[maxn], pre[maxn]; 26 bool spfa(){ 27 for(int i=0;i<=ED;++i) dis[i]= inf, vis[i]= 0; 28 int head= 0, tail= 0; 29 que[tail++]= ST; 30 vis[ST]= 1; 31 dis[ST]= 0; 32 while( head!=tail ){ 33 int u= que[head++]; 34 if( head==maxn ) head= 0; 35 vis[u]= 0; 36 for(int v=0;v<=ED;++v){ 37 if( f[u][v]>0 && up_min( dis[v], dis[u]+c[u][v] ) ){ 38 pre[v]= u; 39 if( !vis[v] ){ 40 que[tail++]= v; 41 if( tail==maxn ) tail= 0; 42 vis[v]= 1; 43 } 44 } 45 } 46 } 47 return dis[ED]!=inf; 48 } 49 50 int mincost(){ 51 int ret= 0; 52 while( spfa() ){ 53 int t= inf; 54 for(int i=ED;i!=ST;i=pre[i]) 55 up_min( t, f[ pre[i] ][i] ); 56 for(int i=ED;i!=ST;i=pre[i]){ 57 f[ pre[i] ][i] -= t; 58 f[i][ pre[i] ] += t; 59 } 60 ret+= t*dis[ED]; 61 } 62 return ret; 63 } 64 65 #define N 55 66 int a[maxn][maxn], b[maxn][maxn]; 67 int solve(){ 68 int i,j; 69 for(i=1;i<=n;++i)for(j=1;j<=k;++j)scanf("%d", &a[i][j]); 70 for(i=1;i<=m;++i)for(j=1;j<=k;++j)scanf("%d", &b[i][j]); 71 72 bool flag= 0; 73 for(int p=1;p<=k;++p){ 74 int s1= 0, s2= 0; 75 for(i=1;i<=n;++i) s1+= a[i][p]; 76 for(i=1;i<=m;++i) s2+= b[i][p]; 77 if( s1>s2 ){ 78 flag= 1; break; 79 } 80 } 81 82 ST= 0, ED= n+m+1; 83 int cost= 0; 84 MM( c, 0 ); 85 for(int p=1;p<=k;++p){ 86 for(i=1;i<=n;++i) 87 for(j=1;j<=m;++j){ 88 scanf("%d", &c[i][n+j]); 89 c[n+j][i]= -c[i][n+j]; 90 } 91 if( flag ) continue; 92 93 MM( f, 0 ); 94 for(i=1;i<=n;++i) f[ST][i]= a[i][p]; 95 for(i=1;i<=m;++i) f[n+i][ED]= b[i][p]; 96 for(i=1;i<=n;++i)for(j=1;j<=m;++j)f[i][n+j]= inf; 97 cost+= mincost(); 98 } 99 if( flag ) cost= -1; 100 return cost; 101 } 102 103 int main() 104 { 105 //freopen("poj2516.in","r",stdin); 106 while( cin>>n>>m>>k, n+m+k ) 107 cout<< solve() <<endl; 108 }
poj2516_2
1 /*2516 Accepted 400K 297MS C++ 2562B 2012-06-22 14:16:59*/ 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 110 18 const int inf= 2100000000; 19 20 int n,m,k; 21 int ST, ED; 22 int c[maxn][maxn], f[maxn][maxn]; 23 24 bool vis[maxn]; 25 int que[maxn+10], dis[maxn], pre[maxn]; 26 bool spfa(){ 27 for(int i=0;i<=ED;++i) dis[i]= inf, vis[i]= 0; 28 int head= 0, tail= 0; 29 que[tail++]= ST; 30 vis[ST]= 1; 31 dis[ST]= 0; 32 while( head!=tail ){ 33 int u= que[head++]; 34 if( head==maxn ) head= 0; 35 vis[u]= 0; 36 for(int v=0;v<=ED;++v){ 37 if( f[u][v]>0 && up_min( dis[v], dis[u]+c[u][v] ) ){ 38 pre[v]= u; 39 if( !vis[v] ){ 40 que[tail++]= v; 41 if( tail==maxn ) tail= 0; 42 vis[v]= 1; 43 } 44 } 45 } 46 } 47 return dis[ED]!=inf; 48 } 49 50 pii mincost(){ 51 int flow= 0, cost= 0; 52 while( spfa() ){ 53 int t= inf; 54 for(int i=ED;i!=ST;i=pre[i]) 55 up_min( t, f[ pre[i] ][i] ); 56 flow+= t; 57 for(int i=ED;i!=ST;i=pre[i]){ 58 f[ pre[i] ][i] -= t; 59 f[i][ pre[i] ] += t; 60 } 61 cost+= t*dis[ED]; 62 } 63 return pii( flow, cost ); 64 } 65 66 #define N 55 67 int a[maxn][maxn], b[maxn][maxn]; 68 int solve(){ 69 ST= 0, ED= n+m+1; 70 int i,j,cost= 0; 71 for(i=1;i<=n;++i)for(j=1;j<=k;++j)scanf("%d", &a[i][j]); 72 for(i=1;i<=m;++i)for(j=1;j<=k;++j)scanf("%d", &b[i][j]); 73 74 bool flag= 0; 75 MM( c, 0 ); 76 for(int p=1;p<=k;++p){ 77 MM( f, 0 ); 78 int ss= 0; 79 for(i=1;i<=n;++i){ 80 ss+= a[i][p]; 81 for(j=1;j<=m;++j){ 82 scanf("%d", &c[i][n+j]); 83 c[n+j][i]= -c[i][n+j]; 84 f[i][n+j]= inf; 85 } 86 } 87 if( flag ) continue; 88 89 for(i=1;i<=n;++i) f[ST][i]= a[i][p]; 90 for(i=1;i<=m;++i) f[n+i][ED]= b[i][p]; 91 pii tmp= mincost(); 92 cost+= tmp.second; 93 if( ss!=tmp.first ) flag= 1; 94 } 95 if( flag ) cost= -1; 96 return cost; 97 } 98 99 int main() 100 { 101 //freopen("poj2516.in","r",stdin); 102 while( cin>>n>>m>>k, n+m+k ) 103 cout<< solve() <<endl; 104 }