poj 2516 最小费用最大流

来源:互联网 发布:中国出境游数据 编辑:程序博客网 时间:2024/05/22 01:39
  1. 最佳匹配的题,m个仓库供应k种商品给n个商家,m*n条运输代价互异,求满足商家需求下的最小运输费用 
  2. 显然,如果某种商品的供货量比需求大,肯定是无法达到要求的,所以开始要判别是否可以得到最佳匹配 
  3.  
  4. 这个题非常有启发意义,刚开始把k种商品一并考虑,tle了,想来也是,这样X集合中的点为m*k,Y中集合为n*k; 
  5. 执行最小费用流这个复杂度为O(n^3)的算法在这个题目是不可以行的 
  6. 考虑到k种商品是相互独立的,所以见k次图,每次图中的点为n+m+2个,这样就可以在时限内出答案了 
  7. */  
  8. #include <stdio.h>  
  9. #include <iostream>  
  10. #include <string.h>  
  11. #include<queue>  
  12. #include<cmath>  
  13. using namespace std;  
  14. const int M=5010,ME=5000000;  
  15. const int INF=0x3f3fffff;  
  16. //******************************  
  17. int Head[M],Next[ME],Num[ME],Flow[ME],Cap[ME],Cost[ME],Q[M],InQ[M],Len[M],pre_edge[M];  
  18. class MaxFlow  
  19. {  
  20. public:  
  21.     void clear()  
  22.     {  
  23.         memset(Head,-1,sizeof(Head));  
  24.         memset(Flow,0,sizeof(Flow));  
  25.     }  
  26.     void addedge(int u,int v,int cap,int cost)  
  27.     {  
  28.         Next[top] = Head[u];  
  29.         Num[top] = v;  
  30.         Cap[top] = cap;  
  31.         Cost[top] = cost;  
  32.         Head[u] = top++;  
  33.    
  34.         Next[top] = Head[v];  
  35.         Num[top] = u;  
  36.         Cap[top] = 0;  
  37.         Cost[top] = -cost;  
  38.         Head[v] = top++;  
  39.     }  
  40.     int solve(int s,int t) //返回最终的cost  
  41.     {  
  42.         int cost = 0;  
  43.         while(SPFA(s,t))  
  44.         {  
  45.             int cur = t,minflow = INF;  
  46.             while(cur != s)  
  47.             {  
  48.                 if(minflow > Cap[pre_edge[cur]]-Flow[pre_edge[cur]])  
  49.                     minflow = Cap[pre_edge[cur]]-Flow[pre_edge[cur]];  
  50.                 cur = Num[pre_edge[cur] ^ 1];  
  51.             }  
  52.             cur = t ;  
  53.             while(cur != s)  
  54.             {  
  55.                 Flow[pre_edge[cur]] += minflow;  
  56.                 Flow[pre_edge[cur] ^ 1] -= minflow;  
  57.                 cost += minflow * Cost[pre_edge[cur]];  
  58.                 cur = Num[pre_edge[cur] ^ 1];  
  59.             }  
  60.         }  
  61.         return cost;  
  62.     }  
  63. private:  
  64.     bool SPFA(int s,int t)  
  65.     {  
  66.         fill(Len,Len+M,INF);  
  67.         Len[s]=0;  
  68.         int head = -1,tail = -1,cur;  
  69.         Q[++head] = s;  
  70.         while(head != tail)  
  71.         {  
  72.             ++tail;  
  73.             if(tail >= M) tail = 0 ;  
  74.             cur = Q[tail];  
  75.             for(int i = Head[cur];i != -1;i = Next[i])  
  76.             {  
  77.                 if(Cap[i]>Flow[i] && Len[Num[i]] > Len[cur] + Cost[i])  
  78.                 {  
  79.                     Len[Num[i]] = Len[cur] + Cost[i];  
  80.                     pre_edge[Num[i]] = i;  
  81.                     if(!InQ[Num[i]])  
  82.                     {  
  83.                         InQ[Num[i]]=true;  
  84.                         ++head;  
  85.                         if(head >= M) head = 0;  
  86.                         Q[head] = Num[i];  
  87.                     }  
  88.                 }  
  89.             }  
  90.             InQ[cur]=false;  
  91.         }  
  92.         return Len[t] != INF;  
  93.     }  
  94.     int top;  
  95. }my;  
  96. //******************************  
  97. int need[55][55],canneed[55];  
  98. int suply[55][55],cansuply[55];  
  99. int trans[55][55][55];  
  100. int main()  
  101. {  
  102.     int n,m,k;  
  103.     while(scanf("%d%d%d",&n,&m,&k),n+m+k)  
  104.     {  
  105.         memset(canneed,0,sizeof(canneed));  
  106.         memset(cansuply,0,sizeof(cansuply));  
  107.         for(int i=1;i<=n;i++)  
  108.         {  
  109.             for(int j=1;j<=k;j++)  
  110.             {  
  111.             scanf("%d",&need[i][j]);  
  112.             canneed[j]+=need[i][j];// 第i个客户j商品的订货量  
  113.             }  
  114.         }  
  115.         for(int i=1;i<=m;i++)  
  116.         {  
  117.             for(int j=1;j<=k;j++)  
  118.             {  
  119.             scanf("%d",&suply[i][j]);  
  120.             cansuply[j]+=suply[i][j];//第i个仓库提供的j商品的量  
  121.             }  
  122.         }  
  123.         for(int i=1;i<=k;i++)  
  124.         {  
  125.             for(int j=1;j<=n;j++)  
  126.             {  
  127.                 for(int f=1;f<=m;f++)  
  128.                 {  
  129.                     scanf("%d",&trans[i][j][f]);//把单位商品i从仓库f运到商户j所需的费用  
  130.                 }  
  131.             }  
  132.         }  
  133.         int flag=1;  
  134.         for(int i=1;i<=k;i++)  
  135.         if(cansuply[i]<canneed[i])  
  136.         {  
  137.             flag=0;  
  138.             break;  
  139.         }  
  140.         if(!flag){puts("-1");continue;}  
  141.         int ans=0;  
  142.         for(int f=1;f<=k;f++)  
  143.         {  
  144.             my.clear();  
  145.             for(int i=1;i<=m;i++)  
  146.             {  
  147.                     my.addedge(0,i,suply[i][f],0);  
  148.                     for(int g=1;g<=n;g++)  
  149.                     {  
  150.                         my.addedge(i,m+g,suply[i][f],trans[f][g][i]);  
  151.                     }  
  152.             }  
  153.             for(int i=1;i<=n;i++)  
  154.             {  
  155.                 my.addedge(m+i,m+n+1,need[i][f],0);  
  156.             }  
  157.             ans+=my.solve(0,m+n+1);  
  158.         }  
  159.         printf("%d\n",ans);  
  160.     }  
  161.     return 0;  
  162. }  
0 0
原创粉丝点击