版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_40924940/article/details/84866523
题目还是网络流,最小费用最大流
因为 m 个仓库, n 个商店,之后还有各个点之间的运输费用,
建图如下:
S 连 仓库,流量为 ai 费用 0,之后把 T 连 商店,流量设为 bi, 费用设为 0, 之后输入 c[i][j] 连一条 i,j路 流量为 INF,费用为 c[i][j]
求最大费用,最小费用。
最小费用跑一下最小费用最大流就好了,
之后最大费用,先把图重置一下,只需要改一下仓库和商店之间的费用为 - c[i][j]跑一边最小费用最大流,输出绝对值就好了。
以下为AC 代码
#include<cstdio>
#include<queue>
#include<iostream>
#include<cstring>
using namespace std;
const int maxn = 1e5+5
const int INF = 0x3f3f3f3f
int n,m;
int s,t;
int dis[maxn],flow[maxn],pre[maxn];
int tot=1,head[maxn];
struct edge
{
int t,next,w,f;
}e[100005];
void add(int u,int v,int w,int f)
{
tot++;e[tot].t=v;e[tot].next=head[u];e[tot].w=w;e[tot].f=f;head[u]=tot;
tot++;e[tot].t=u;e[tot].next=head[v];e[tot].w=0;e[tot].f=-f;head[v]=tot;
}
bool vis[maxn];
bool spfa(int s,int t)
{
memset(dis,INF,sizeof dis);
memset(vis,0,sizeof vis);
queue<int> q;
dis[s]=0;
vis[s]=1;
flow[s]=INF;
q.push(s);
while(q.size())
{
int u=q.front();
q.pop();
vis[u]=false;
for (int h=head[u];~h;h=e[h].next)
{
int v = e[h].t;
int f = e[h].f;
if (e[h].w && dis[u] + f < dis[v])
{
dis[v]=dis[u] + f;
flow[v]=min(flow[u], e[h].w);
pre[v]=h;
if(!vis[v])
{
vis[v]=true;
q.push(v);
}
}
}
}
return dis[t]!=INF;
}
int mcost,mflow;
void dfs(int s,int t)
{
int x = t;
while(x != s)
{
int i = pre[x];
e[i].w -= flow[t];
e[i ^ 1].w += flow[t];
x = e[i ^ 1].t;
}
mflow += flow[t];
mcost += flow[t]*dis[t];
}
void E_K(int s,int t)
{
while(spfa(s,t))
dfs(s,t);
}
int a[maxn],b[maxn],c[maxn][maxn];
int main()
{
scanf("%d%d",&m,&n);
memset(head,-1,sizeof head);
s=0, t=m+n+1;
for(int i=1;i<=m;i++)
{
scanf("%d",&a[i]);
add(s,i,a[i],0);
}
for(int i=1;i<=n;i++)
{
scanf("%d",&b[i]);
add(i+m,t,b[i],0);
}
for(int i=1;i<=m;i++)
{
for(int j=1;j<=n;j++)
{
scanf("%d",&c[i][j]);
add(i,j+m,INF,c[i][j]);
}
}
E_K(s, t);
printf("%d\n",mcost);
memset(head,-1,sizeof head);
memset(e,0,sizeof e);
memset(flow,0,sizeof flow);
memset(pre,0,sizeof pre);
mcost=0;
for(int i=1;i<=m;i++)
{
add(s,i,a[i],0);
}
for(int i=1;i<=n;i++)
{
add(i+m,t,b[i],0);
}
for(int i=1;i<=m;i++)
{
for (int j=1;j<=n;j++)
{
add(i,j+m,INF,-c[i][j]);
}
}
E_K(s,t);
printf("%d\n",-mcost);
return 0;
}