第一行是三个数字:N,M,K
分别表示有N个商店,M个供货商,K中货物
分别表示有N个商店,M个供货商,K中货物
接下来是N行,每行K个整数
对于第i行第j列,表示的是第i个商店对于货物j的需求
对于第i行第j列,表示的是第i个商店对于货物j的需求
再接着,M行,每行K个整数
对于第i行第j列,表示的是第i个供货商对于货物j的存货
对于第i行第j列,表示的是第i个供货商对于货物j的存货
接下来有K个N*M的矩形
第X个矩形的第i行第j列表示的是
从供货商j 运送一个单位的 货物X 到商店i的 花费
第X个矩形的第i行第j列表示的是
从供货商j 运送一个单位的 货物X 到商店i的 花费
最后要求的是
在满足 所有商店的供应的 情况下的 最小花费
如果无法满足,则输出-1
在满足 所有商店的供应的 情况下的 最小花费
如果无法满足,则输出-1
题解:
首先弄清楚题目的意思
考虑k种货物都是独立的,因此只需要考虑k遍最小的费用然后求和
对于每一次的最小费用,显然直接求解最小费用流即可,
对于图的构建并不难,
但是要考虑清楚每条边的容量
从汇点向每个供货商连接一条容量为存货数量,费用为0的边
然后从每个供货商向每个商店连接一条容量为INF,费用为花费的边(容量连接成存货数量也行)
从商店向汇点连接一条容量为需求,费用为0的边
求解K次最小费用流累加答案即可。
参考链接:https://blog.csdn.net/qq_30974369/article/details/76648579
首先弄清楚题目的意思
考虑k种货物都是独立的,因此只需要考虑k遍最小的费用然后求和
对于每一次的最小费用,显然直接求解最小费用流即可,
对于图的构建并不难,
但是要考虑清楚每条边的容量
从汇点向每个供货商连接一条容量为存货数量,费用为0的边
然后从每个供货商向每个商店连接一条容量为INF,费用为花费的边(容量连接成存货数量也行)
从商店向汇点连接一条容量为需求,费用为0的边
求解K次最小费用流累加答案即可。
参考链接:https://blog.csdn.net/qq_30974369/article/details/76648579
代码:
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #include <queue> 5 #include <cmath> 6 using namespace std; 7 const int maxn = 210; 8 const int maxm = 1000; 9 const int INF = 0x3f3f3f3f; 10 struct edge 11 { 12 int v, next, cap, flow, cost; 13 int x, y; 14 } e[maxn*maxn]; 15 struct shudui 16 { 17 int s[55]; 18 }p1[55],p2[55]; 19 int c[55][55][55]; 20 int head[maxn],tol; 21 int pre[maxn],dis[maxn]; 22 bool vis[maxn]; 23 void init() 24 { 25 tol = 0; 26 memset(head, -1, sizeof(head)); 27 } 28 void add_edge(int x,int y,int cap,int cost) 29 { 30 e[tol].v=y; 31 e[tol].cap=cap; 32 e[tol].flow=0; 33 e[tol].cost=cost; 34 e[tol].next=head[x]; 35 head[x]=tol++; 36 37 e[tol].v=x; 38 e[tol].cap=0; 39 e[tol].flow=0; 40 e[tol].cost=-cost; 41 e[tol].next=head[y]; 42 head[y]=tol++; 43 } 44 int spfa(int s,int t) 45 { 46 queue<int>r; 47 for(int i=0;i<maxn;++i) 48 { 49 vis[i]=0; 50 dis[i]=INF; 51 pre[i]=-1; 52 } 53 dis[s]=0; 54 vis[s]=1; 55 r.push(s); 56 while(!r.empty()) 57 { 58 59 int u=r.front(); 60 r.pop(); 61 vis[u]=0; 62 for(int i=head[u];i!=-1;i=e[i].next) 63 { 64 int v=e[i].v; 65 if(e[i].cap>e[i].flow && dis[v]>dis[u]+e[i].cost) 66 { 67 dis[v]=dis[u]+e[i].cost; 68 pre[v]=i; 69 if(!vis[v]) 70 { 71 vis[v]=1; 72 r.push(v); 73 } 74 } 75 } 76 } 77 if(pre[t]==-1) return 0; 78 else return 1; 79 } 80 int MincostMaxflow(int s,int t,int &cost) 81 { 82 int flow=0; 83 cost=0; 84 while(spfa(s,t)) 85 { 86 int minn=INF; 87 for(int i=pre[t];i!=-1;i=pre[e[i^1].v]) 88 { 89 if(minn>e[i].cap-e[i].flow) 90 { 91 minn=e[i].cap-e[i].flow; 92 } 93 } 94 for(int i=pre[t];i!=-1;i=pre[e[i^1].v]) 95 { 96 e[i].flow+=minn; 97 e[i^1].flow-=minn; 98 cost+=e[i].cost*minn; 99 } 100 flow+=minn; 101 } 102 return flow; 103 } 104 105 int main() 106 { 107 int n,m,k,st,en; 108 char s[105][105]; 109 while(~scanf("%d%d%d",&n,&m,&k) && n+m+k) 110 { 111 for(int i=1;i<=n;++i) 112 { 113 for(int j=1;j<=k;++j) 114 scanf("%d",&p1[i].s[j]); 115 } 116 for(int i=1;i<=m;++i) 117 { 118 for(int j=1;j<=k;++j) 119 scanf("%d",&p2[i].s[j]); 120 } 121 for(int ii=1;ii<=k;++ii) 122 { 123 for(int i=1;i<=n;++i) 124 { 125 for(int j=1;j<=m;++j) 126 { 127 scanf("%d",&c[ii][i][j]); 128 } 129 } 130 } 131 st=0; 132 en=n+m+1; 133 int sum=0,flag=0; 134 135 for(int ii=1;ii<=k;++ii) 136 { 137 init(); 138 int ans1=0,ans2=0; 139 for(int i=1;i<=n;++i) 140 { 141 add_edge(st,i,p1[i].s[ii],0); 142 ans1+=p1[i].s[ii]; 143 } 144 for(int i=1;i<=n;++i) 145 { 146 for(int j=1;j<=m;++j) 147 { 148 add_edge(i,n+j,INF,c[ii][i][j]); 149 } 150 } 151 for(int i=1;i<=m;++i) 152 { 153 add_edge(n+i,en,p2[i].s[ii],0); 154 ans2+=p2[i].s[ii]; 155 } 156 if(ans1>ans2) 157 { 158 flag=1; 159 break; 160 } 161 int ans=0; 162 MincostMaxflow(st,en,ans); 163 sum+=ans; 164 //printf("----------------- "); 165 } 166 if(flag) 167 printf("-1 "); 168 else 169 printf("%d ",sum); 170 } 171 return 0; 172 }