洛谷P4015

版权声明:本文为博主原创文章,未经博主允许不得转载。 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;
}

猜你喜欢

转载自blog.csdn.net/qq_40924940/article/details/84866523