poj 2516 Minimum Cost (最小费用流 )

题意:有N个客户,M个仓库,和K种货物。已知每个客户需要每种货物的数量,每个仓库存储每种货物的数量,每个仓库运输各种货物去各个客户的单位费用。判断所有的仓库能否满足所有客户的需求,如果可以,求出最少的运输总费用。

 

思路:最小费用最大流。先判断是否每种货物的存储总量都足够,足够的话,对每一种货物进行一次最小费用最大流求出完成这种货物运输的最小总费用,所有的总费用相加就是结果了。

 

 

思路:最小费用最大流。先判断是否每种货物的存储总量都足够,

     足够的话,对每一种货物进行一次最小费用最大  流求出完成这种货物运输的最小总费用,所有的总费用相加就是结果了。

  http://poj.org/problem?id=2516

  1 #include<stdio.h>

  2 #define maxn 200

  3 #define inf 0x7fffffff

  4 #include<string.h>

  5 int  need[maxn][maxn],needk[maxn],have[maxn][maxn],havek[maxn],cap[maxn][maxn],map[maxn][maxn];

  6 int que[maxn],ans,pre[maxn];

  7 int n,m,k,max;

  8 int dis[maxn],vis[maxn];

  9 int min(int x,int y)

 10 {

 11     if(x<y)return x;

 12     else  return y;

 13 }

 14 int SPFA()

 15 {

 16     int i,head=0,tail=0;

 17     for(i=0;i<=max;i++)

 18     {

 19         dis[i]=inf;

 20         vis[i]=0;

 21     }

 22     dis[0]=0;

 23     vis[0]=1;

 24     que[head]=0;

 25     tail++;

 26     while(head!=tail)

 27     {

 28 

 29         int u=que[head];

 30         vis[u]=0;

 31         for(i=0;i<=max;i++)

 32         {

 33             if(cap[u][i]&&dis[i]>dis[u]+map[u][i])

 34             {

 35 

 36                 dis[i]=dis[u]+map[u][i];

 37                 pre[i]=u;

 38                 if(!vis[i])

 39                 {

 40                     vis[i]=1;

 41                     que[tail++]=i;

 42                     if(tail==maxn)tail=0;

 43                 }

 44             }

 45         }

 46         head++;

 47         if(head==maxn)head=0;

 48     }

 49     if(dis[max]==inf)return 0;

 50     else return 1;

 51 }

 52 void Update()

 53 {

 54     int i,sum=inf;

 55     for(i=max;i!=0;i=pre[i])

 56     {

 57         sum=min(sum,cap[pre[i]][i]);//寻找(最短)增广路经上的最小 流量

 58     }

 59 

 60     for(i=max;i!=0;i=pre[i])

 61     {

 62         cap[pre[i]][i]-=sum;

 63         cap[i][pre[i]]+=sum;

 64         ans+=map[pre[i]][i]*sum;

 65 

 66     }

 67 

 68 }

 69 int main()

 70 {

 71     int i,j,l;

 72   while(scanf("%d%d%d",&n,&m,&k)!=EOF)

 73   {

 74       if(n==0&&m==0&&k==0)break;

 75       memset(needk,0,sizeof(needk));

 76       memset(havek,0,sizeof(havek));

 77       for(i=1;i<=n;i++)

 78       {

 79           for(j=1;j<=k;j++)

 80           {

 81               scanf("%d",&need[i][j]);

 82               needk[j]+=need[i][j];

 83           }

 84       }

 85 

 86       for(i=1;i<=m;i++)

 87       {

 88           for(j=1;j<=k;j++)

 89           {

 90               scanf("%d",&have[i][j]);

 91               havek[j]+=have[i][j];

 92           }

 93       }

 94       int f=0;

 95       ans=0;

 96       for(i=1;i<=k;i++)

 97       {

 98           if(needk[i]>havek[i])

 99           {

100               f=1;

101               break;

102           }

103       }

104 

105       max=n+m+1;

106       for(i=1;i<=k;i++)

107       {

108           memset(cap,0,sizeof(cap));

109           for(j=1;j<=n;j++)

110           {

111               for(l=1;l<=m;l++)

112               {

113                   scanf("%d",&map[l][j+m]);

114                   map[j+m][l]=-map[l][j+m];

115                   cap[l][j+m]=inf;

116 

117               }

118           }

119 

120           for(j=1;j<=m;j++)

121           {

122               cap[0][j]=have[j][i];

123               map[0][j]=map[j][0]=0;

124 

125           }

126           for(j=1;j<=n;j++)

127           {

128               cap[j+m][max]=need[j][i];

129               map[j+m][max]=map[max][j+m]=0;

130           }

131 

132           while(SPFA())Update();//最小费用算法

133 

134       }

135       if(!f)printf("%d\n",ans);

136       else printf("-1\n");

137   }

138 }

你可能感兴趣的:(poj)