Time Limit: 4000MS | Memory Limit: 65536K | |
Total Submissions: 8085 | Accepted: 2653 |
Description
Input
Output
Sample Input
1 3 3 1 1 1 0 1 1 1 2 2 1 0 1 1 2 3 1 1 1 2 1 1 1 1 1 3 2 20 0 0 0
Sample Output
4 -1
Source
POJ Monthly--2005.07.31, Wang Yijie
分析:这题既可以用KM算法,又可以用最大流最小费用。。。两种算法我都不会耶,于是。。。拿来当练习。。。
KM算法:
#include <stdio.h> const int MAX = 51; const int MAXX= 151; int n,m,k,nx,ny,slack; int get[MAX] [MAX],order[MAX][MAX],store[MAX][MAX]; int w[MAXX][MAXX],lx [MAXX], ly [MAXX],match [MAXX],can[MAXX]; bool sx [MAXX], sy [MAXX],flag; inline int max(int a,int b){return(a>b?a:b);} inline int min(int a,int b){return(a<b?a:b);} inline void makegraph(int x) { int i,j; nx=0,ny=0; for(i=1; i<=n; ++i) for(j=1; j<=order[i][x]; ++j)lx[++nx]=i; for(i=1; i<=m; ++i) for(j=1; j<=store[i][x]; ++j)ly[++ny]=i; for(i=1; i<=nx; ++i) for(j=1; j<=ny; ++j)w[i][j]=get[lx[i]][ly[j]]; } bool path(int u) { sx[u]=1; for(int v = 1;v <=ny;++v) { if(sy[v]) continue; int temp = w[u][v] - lx[u] - ly[v]; if(temp == 0) { sy[v] = 1; if(!match[v] || path(match[v])) { can[u]=v; match[v] = u; return 1; } } else slack =min(slack,temp); } return 0; } int KM() { int i,j; for(i=1;i<=nx;++i) { lx[i]=0x7FFFFFFF; for(j=1;j<=ny;++j)match[j]=0,ly[j]=0,lx[i]=min(lx[i],w[i][j]); } for(int u=1;u <=nx;++u) while(1) { for(i=1;i<=nx;++i)sx[i]=0; for(i=1;i<=ny;++i)sy[i]=0; slack=0x7FFFFFFF; if(path(u)) break; for(i=1;i<=nx;++i) if(sx[i])lx[i]+=slack; for(j=1;j<=ny;++j) if(sy[j])ly[j]-=slack; } int sum=0; for(i=1; i<=nx; ++i)sum+=w[i][can[i]]; return sum; } inline int in() { char ch; int a=0; while(!(((ch=getchar())>='0')&&(ch<='9'))); a*=10;a+=ch-'0'; while(((ch=getchar())>='0')&&(ch<='9'))a*=10,a+=ch-'0'; return a; } int main() { int i,j,h,cost,s1,s2; while(n=in(),m=in(),k=in()) { for(i=1;i<=k;++i)can[i]=0; for(i=1; i<=n; ++i) for(j=1; j<=k; ++j)order[i][j]=in(); for(i=1; i<=m; ++i) for(j=1; j<=k; ++j)store[i][j]=in(); flag=1; for(j=1;j<=k;++j) { s1=s2=0; for(i=1;i<=n;++i)s1+=order[i][j]; for(i=1;i<=m;++i)s2+=store[i][j]; if(s1>s2) { flag=0; break; } } cost=0; for(h=1; h<=k; ++h) { for(i=1; i<=n; ++i) for(j=1; j<=m; ++j)get[i][j]=in(); if(flag)makegraph(h),cost+=KM(); } printf("%d/n",(flag?cost:-1)); } return 0; }
最小费用流:
#include <stdio.h> #include <string.h> const int MN=52; const int MM=110; const int INF=0x7f7f7f7f; int n,m,k; int order[MN][MN],store[MN][MN],mat[MN][MN]; int queue[MM],flow[MM][MM],c[MM][MM],cost[MM][MM],pre[MM],dis[MM],mf[MM]; bool visit[MM],flag; inline int MIN(int x,int y) { return x<y?x:y; } inline void get(int& a) { char ch=getchar(); while (ch<'0'||ch>'9') ch=getchar(); for (a=0; ch>='0'&&ch<='9'; ch=getchar()) a=a*10+ch-48; } inline void ConstructMap(int p,int t) { int i,j,k; memset(c,0,sizeof(c)); memset(cost,0,sizeof(cost)); for(i=1; i<=m; ++i)c[0][i]=store[i][p]; for(i=1; i<=m; ++i) for(j=1; j<=n; ++j) { k=j+m; c[i][k]=INF; cost[i][k]=mat[j][i]; cost[k][i]=-mat[j][i]; } for (i=1; i<=n; ++i)c[i+m][t]=order[i][p]; } inline bool spfa( int n, int s, int t ) { int top,tail,u,i,v; memset(dis,0x7f,sizeof(dis)); memset(visit,1,sizeof(visit)); memset(pre,-1,sizeof(pre)); dis[s]=0,top=0,tail=1,queue[0]=s,visit[s]=0,mf[s]=INF; while(top!=tail) { u=queue[top],visit[u]=1; ++top; if (top==n)top=0; for(v=0; v<n;++v) if(c[u][v]>flow[u][v]&&dis[v]-cost[u][v]>dis[u]) { dis[v]=dis[u]+cost[u][v]; mf[v]=MIN(mf[u],c[u][v]-flow[u][v]); pre[v]=u; if(visit[v]) { queue[tail]=v,visit[v]=0; ++tail; if(tail==n)tail=0; } } } return(pre[t]>=0); } inline int Min_Cost_Max_Flow(int n,int s,int t) { int i, j,u,v,ans=0; memset(flow,0,sizeof(flow)); while(spfa(n,s,t)) { for(u=pre[v=t];v!=0;v=u,u=pre[v]) { flow[u][v]+=mf[t]; flow[v][u]-=mf[t]; } ans+=mf[t]*dis[t]; } return ans; } int main() { int i,j,p,sum,s1,s2; while(get(n),get(m),get(k),k) { for(i=1;i<=n;++i) for(j=1;j<=k;++j) get(order[i][j]); for(i=1;i<=m;++i) for(j=1;j<=k;++j) get(store[i][j]); sum=0,flag=1; for(j=1;j<=k;++j) { s1=s2=0; for(i=1;i<=n;++i)s1+=order[i][j]; for(i=1;i<=m;++i)s2+=store[i][j]; if(s1>s2) { flag=0; break; } } for(p=1;p<=k;++p) { for(i=1;i<=n;++i) for(j=1;j<=m;++j) get(mat[i][j]); if (flag)ConstructMap(p,n+m+1),sum+=Min_Cost_Max_Flow(n+m+2,0,n+m+1); } printf("%d/n",(flag?sum:-1)); } return 0; }