第一行是三个数字: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("-----------------\n");
165 }
166 if(flag)
167 printf("-1\n");
168 else
169 printf("%d\n",sum);
170 }
171 return 0;
172 }
