Time Limit: 4000MS | Memory Limit: 65536K | |
Total Submissions: 10978 | Accepted: 3692 |
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
#include<stdio.h> #include<iostream> #include<algorithm> #include<string.h> #include<queue> using namespace std; //************************************************************ //最小费用最大流算法 //SPFA求最短路 //邻接矩阵形式 //初始化:cap:容量,没有边为0 //cost:耗费,对称形式,没有边的也为0 //c是最小费用 //f是最大流 //******************************************************* const int MAXN=200; const int INF=0x3fffffff; int cap[MAXN][MAXN];//容量,没有边为0 int flow[MAXN][MAXN]; //耗费矩阵是对称的,有i到j的费用,则j到i的费用为其相反数 int cost[MAXN][MAXN]; int n;//顶点数目0~n-1 int f;//最大流 int c;//最小费用 int start,end;//源点和汇点 bool vis[MAXN];//在队列标志 int que[MAXN]; int pre[MAXN]; int dist[MAXN];//s-t路径最小耗费 bool SPFA() { int front=0,rear=0; for(int u=0;u<=n;u++) { if(u==start) { que[rear++]=u; dist[u]=0; vis[u]=true; } else { dist[u]=INF; vis[u]=false; } } while(front!=rear) { int u=que[front++]; vis[u]=false; if(front>=MAXN)front=0; for(int v=0;v<=n;v++) { if(cap[u][v]>flow[u][v]&&dist[v]>dist[u]+cost[u][v]) { dist[v]=dist[u]+cost[u][v]; pre[v]=u; if(!vis[v]) { vis[v]=true; que[rear++]=v; if(rear>=MAXN)rear=0; } } } } if(dist[end]>=INF)return false; return true; } void minCostMaxflow() { memset(flow,0,sizeof(flow)); c=f=0; while(SPFA()) { int Min=INF; for(int u=end;u!=start;u=pre[u]) Min=min(Min,cap[pre[u]][u]-flow[pre[u]][u]); for(int u=end;u!=start;u=pre[u]) { flow[pre[u]][u]+=Min; flow[u][pre[u]]-=Min; } c+=dist[end]*Min; f+=Min; } } //************************************************************ int order[MAXN][MAXN]; int supply[MAXN][MAXN]; int tolorder[MAXN]; int main() { //freopen("in.txt","r",stdin); // freopen("out.txt","w",stdout); int N,M; int K; while(scanf("%d%d%d",&N,&M,&K)!=EOF) { if(N==0&&M==0&&K==0)break; start=0; n=N+M+1; end=n; memset(cap,0,sizeof(cap)); memset(cost,0,sizeof(cost)); for(int i=0;i<N;i++) for(int j=0;j<K;j++) scanf("%d",&order[i][j]); for(int i=0;i<M;i++) for(int j=0;j<K;j++) scanf("%d",&supply[i][j]); for(int i=0;i<K;i++) { tolorder[i]=0; for(int j=0;j<N;j++) tolorder[i]+=order[j][i]; } for(int i=1;i<=M;i++) for(int j=M+1;j<=N+M;j++) cap[i][j]=INF; bool flag=true; int ans=0; for(int i=0;i<K;i++) { for(int j=M+1;j<=M+N;j++) for(int k=1;k<=M;k++) { scanf("%d",&cost[k][j]); cost[j][k]=-cost[k][j]; } if(!flag)continue; for(int j=1;j<=M;j++) cap[start][j]=supply[j-1][i]; for(int j=1;j<=N;j++) cap[j+M][end]=order[j-1][i]; /* for(int k=0;k<=n;k++) { for(int j=0;j<=n;j++) printf("%d ",cap[k][j]); printf("\n"); } */ minCostMaxflow(); // printf("%d %d\n",f,c); if(f<tolorder[i])flag=false; else ans+=c; } if(!flag)printf("-1\n"); else printf("%d\n",ans); } return 0; }