學了最小費用流的增廣路演算法後,就用它寫了
對於每個物品,分別建圖求一次最小費用流,把結果相加就行
少打了一個break,查了1個小時。。。唉
代碼:
#include<iostream><br />#include<queue><br />using namespace std;<br />#define MAX 120<br />#define inf 99999999<br />int pre[MAX],c[MAX][MAX],f[MAX][MAX],b[MAX][MAX],cost[MAX][MAX][MAX];<br />int order[MAX][MAX],store[MAX][MAX],d[MAX],need[MAX],total[MAX];<br />bool vis[MAX];<br />int n,m,k,s,t,ans,max_flow,min_cost;<br />void spfa()<br />{<br />int i,j;<br />queue<int>q;<br />memset(vis,0,sizeof(vis));<br />while(!q.empty())<br />q.pop();<br />q.push(s);<br />vis[s]=true;<br />while(!q.empty())<br />{<br />i=q.front();<br />q.pop();<br />vis[i]=false;<br />for(j=0;j<=n+m+1;j++)<br />{<br />if(c[i][j]>f[i][j]&&d[j]>d[i]+b[i][j])<br />{<br />d[j]=d[i]+b[i][j];<br />pre[j]=i;<br />if(!vis[j])<br />{<br />q.push(j);<br />vis[j]=true;<br />}<br />}<br />}<br />}<br />}<br />void mcmf()<br />{<br />int i,minf;<br />while(true)<br />{<br />memset(pre,-1,sizeof(pre));<br />for(i=0;i<=n+m+1;i++)<br />d[i]=inf;<br />d[s]=0;<br />spfa();<br />if(pre[t]==-1)<br />break;<br />i=t;<br />minf=inf;<br />while(pre[i]!=-1)<br />{<br />if(c[pre[i]][i]-f[pre[i]][i]<minf)<br />{<br />minf=c[pre[i]][i]-f[pre[i]][i];<br />}<br />i=pre[i];<br />}<br />i=t;<br />while(pre[i]!=-1)<br />{<br />f[pre[i]][i]+=minf;<br />f[i][pre[i]]=-f[pre[i]][i];<br />i=pre[i];<br />}<br />//ans+=d[t]; //每條邊費用不為0的邊上的流量不一定為1<br />}<br />}<br />int main()<br />{<br />int i,j,l,flag;<br />while(scanf("%d %d %d",&n,&m,&k)!=EOF)<br />{<br />if(n==0&&m==0&&k==0)<br />break;<br />memset(need,0,sizeof(need));<br />memset(total,0,sizeof(total));<br />ans=0;<br />s=0;<br />t=n+m+1;<br />for(i=1;i<=n;i++)<br />{<br />for(j=1;j<=k;j++)<br />{<br />scanf("%d",&order[i][j]);<br />need[j]+=order[i][j];//j種貨物需求量<br />}<br />}<br />for(i=1;i<=m;i++)<br />{<br />for(j=1;j<=k;j++)<br />{<br />scanf("%d",&store[i][j]);<br />total[j]+=store[i][j];//j種貨物供應量<br />}<br />}<br />for(l=1;l<=k;l++)<br />{<br />for(i=1;i<=n;i++)<br />for(j=1;j<=m;j++)<br />{<br />scanf("%d",&cost[l][j][i]);<br />}<br />}<br />flag=1;<br />for(i=1;i<=k;i++)<br />{<br />if(need[i]>total[i])<br />{<br />printf("-1/n");<br />flag=0;<br />break;//一開始少了個break,可能一組資料輸出多個-1<br />}<br />}<br />if(flag)<br />{<br />for(l=1;l<=k;l++)<br />{<br />memset(c,0,sizeof(c));<br />memset(f,0,sizeof(f));<br />memset(b,0,sizeof(b));<br />for(i=1;i<=m;i++)<br />c[s][i]=store[i][l];//源點向倉庫連邊,容量為該倉庫第l種貨物的儲量<br />for(i=1;i<=n;i++)<br />c[i+m][t]=order[i][l];//每個商店向匯點連邊,容量為該商店的需求量<br />for(i=1;i<=m;i++)<br />{<br />for(j=1;j<=n;j++)<br />{<br />c[i][j+m]=store[i][l];//每個倉庫i能為每個商店j提供該倉庫中的所有l號貨物<br />b[i][j+m]=cost[l][i][j];<br />b[j+m][i]=-b[i][j+m];//表示逆流費用與正流相反<br />}<br />}<br />mcmf();<br />for(i=1;i<=m;i++)<br />for(j=1;j<=n;j++)<br />ans+=f[i][j+m]*b[i][j+m];//求最小費用<br />}<br />printf("%d/n",ans);<br />}<br />}<br />//system("pause");<br />return 0;<br />}