POJ2516 Minimum Cost(最小费用最大流)

一开始我把每个店主都拆成k个点,然后建图。。然后TLE。。

看题解= =哦,愚钝了,k个商品是独立的,可以分别跑k次最小费用最大流,结果就是k次总和。。

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<queue>
  4 #include<algorithm>
  5 using namespace std;
  6 #define INF (1<<30)
  7 #define MAXN 111
  8 #define MAXM 111*111*2
  9 struct Edge{
 10     int u,v,cap,cost,next;
 11 }edge[MAXM];
 12 int head[MAXN];
 13 int NV,NE,vs,vt;
 14 
 15 void addEdge(int u,int v,int cap,int cost){
 16     edge[NE].u=u; edge[NE].v=v; edge[NE].cap=cap; edge[NE].cost=cost;
 17     edge[NE].next=head[u]; head[u]=NE++;
 18     edge[NE].u=v; edge[NE].v=u; edge[NE].cap=0; edge[NE].cost=-cost;
 19     edge[NE].next=head[v]; head[v]=NE++;
 20 }
 21 bool vis[MAXN];
 22 int d[MAXN],pre[MAXN];
 23 bool SPFA(){
 24     for(int i=0;i<NV;++i){
 25         vis[i]=0;
 26         d[i]=INF;
 27     }
 28     vis[vs]=1;
 29     d[vs]=0;
 30     queue<int> que;
 31     que.push(vs);
 32     while(!que.empty()){
 33         int u=que.front(); que.pop();
 34         for(int i=head[u]; i!=-1; i=edge[i].next){
 35             int v=edge[i].v;
 36             if(edge[i].cap && d[v]>d[u]+edge[i].cost){
 37                 d[v]=d[u]+edge[i].cost;
 38                 pre[v]=i;
 39                 if(!vis[v]){
 40                     vis[v]=1;
 41                     que.push(v);
 42                 }
 43             }
 44         }
 45         vis[u]=0;
 46     }
 47     return d[vt]!=INF;
 48 }
 49 int MCMF(){
 50     int res=0;
 51     while(SPFA()){
 52         int flow=INF,cost=0;
 53         for(int u=vt; u!=vs; u=edge[pre[u]].u){
 54             flow=min(flow,edge[pre[u]].cap);
 55         }
 56         for(int u=vt; u!=vs; u=edge[pre[u]].u){
 57             edge[pre[u]].cap-=flow;
 58             edge[pre[u]^1].cap+=flow;
 59             cost+=flow*edge[pre[u]].cost;
 60         }
 61         res+=cost;
 62     }
 63     return res;
 64 }
 65 
 66 int n,m,k,mat[55][55][55],to[55][55],from[55][55];
 67 bool isOK(int *need,int *supply){
 68     for(int i=0; i<k; ++i) if(need[i]>supply[i]) return 0;
 69     return 1;
 70 }
 71 int main(){
 72     int a;
 73     while(~scanf("%d%d%d",&n,&m,&k) && (n||m||k)){
 74         int sum=0;
 75         int supply[55]={0},need[55]={0};
 76         for(int i=0; i<n; ++i){
 77             for(int j=0; j<k; ++j){
 78                 scanf("%d",&to[i][j]);
 79                 need[j]+=to[i][j];
 80             }
 81         }
 82         for(int i=0; i<m; ++i){
 83             for(int j=0; j<k; ++j){
 84                 scanf("%d",&from[i][j]);
 85                 supply[j]+=from[i][j];
 86             }
 87         }
 88         for(int z=0; z<k; ++z){
 89             for(int x=0; x<n; ++x){
 90                 for(int y=0; y<m; ++y) scanf("%d",&mat[z][x][y]);
 91             }
 92         }
 93         if(!isOK(need,supply)){
 94             puts("-1");
 95             continue;
 96         }
 97 
 98         vs=n+m; vt=vs+1; NV=n+m+2;
 99         int res=0;
100         for(int good=0; good<k; ++good){
101             NE=0;
102             memset(head,-1,sizeof(head));
103 
104             for(int i=0; i<m; ++i) addEdge(vs,i,from[i][good],0);
105             for(int i=0; i<n; ++i) addEdge(i+m,vt,to[i][good],0);            
106             for(int i=0; i<n; ++i){
107                 for(int j=0; j<m; ++j) addEdge(j,i+m,INF,mat[good][i][j]);
108             }
109             res+=MCMF();
110         }
111         printf("%d\n",res);
112     }
113     return 0;
114 }

 

posted @ 2015-10-05 16:30  WABoss  阅读(1061)  评论(0编辑  收藏  举报