登 录
赤裸裸的最小费用最大流。构建超级源点和超级汇点,源点出边的容量等于对应节点的储量,汇点入边的容量等于对应节点的需求量。
总结:本题因为用数组做队列时预留的空间不够,贡献了数次RE。
#include <iostream> using namespace std; #define MAXN 105 #define MIN(x,y) (x<y?x:y) #define INF 2000005 int map[MAXN][MAXN],cost[MAXN][MAXN]; int pre[MAXN],min_flow[MAXN];//记录结点的父节点 当前路径中最小的一段的值,也即限制值 int flow[MAXN][MAXN];//记录当前网络中的流 int dist[MAXN];//SPFA用 bool SPFA(int num,int source,int sink) { int my_queue[MAXN*100];//数组实现队列,必须预留比较大的空间 for(int i=0;i<num;i++) { dist[i]=INF; } dist[source]=0; int queue_first=0;//初始化队列 int queue_end=0; my_queue[queue_end++]=source; memset(pre,-1,sizeof(pre)); min_flow[source]=INF; while(queue_first<queue_end) { int temp=my_queue[queue_first++]; for(int i=0;i<num;i++) { if((map[temp][i]-flow[temp][i]>0)&&(dist[temp]+cost[temp][i]<dist[i])) { dist[i]=dist[temp]+cost[temp][i]; my_queue[queue_end++]=i;//加入队列 pre[i]=temp; min_flow[i]=MIN(min_flow[temp],(map[temp][i]-flow[temp][i]));//求得min_flow } } } if(pre[sink]!=-1) return true;//sink的父节点不为初始值,说明已经找到了一条路径 return false; } int Min_Cost_Max_Flow(int num,int source,int sink)//参数含义:结点数量 源点 汇点 { int ans=0; memset(flow,0,sizeof(flow)); while(SPFA(num,source,sink))//一直循环,直到不存在增广路径 { int k=sink; while(pre[k]>=0) { flow[pre[k]][k]+=min_flow[sink];//将新的流量加入flow flow[k][pre[k]]=-flow[pre[k]][k]; k=pre[k]; } ans+=dist[sink]*min_flow[sink]; } return ans; } int main() { int N,M,K,ans; bool no_ans; int order[MAXN][MAXN],storage[MAXN][MAXN]; while(scanf("%d%d%d",&N,&M,&K)&&N!=0) { no_ans=false; ans=0; 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",&storage[i][j]); } } for(int i=0;i<K;i++) { int sum1=0,sum2=0; for(int j=0;j<N;j++) { sum1+=order[j][i]; } for(int j=0;j<M;j++) { sum2+=storage[j][i]; } if(sum1>sum2) { no_ans=true; ans=-1; break; } } for(int i=0;i<K;i++) { memset(cost,0,sizeof(cost)); for(int j=0;j<N;j++) { for(int k=0;k<M;k++) { scanf("%d",&cost[N+k][j]); cost[j][N+k]=-cost[N+k][j]; } } if(no_ans) continue; else { memset(map,0,sizeof(map)); for(int j=0;j<N;j++) map[j][N+M]=order[j][i];//构建汇点 for(int j=0;j<M;j++) map[N+M+1][j+N]=storage[j][i];//构建源点 for(int j=N;j<N+M;j++) for(int k=0;k<N;k++) map[j][k]=10; ans+=Min_Cost_Max_Flow(M+N+2,M+N+1,M+N); } } printf("%d/n",ans); } return 0; }
抱歉!评论已关闭.