luogu p4015(最小费用最大流)

传送门

题意:

有\(m\)个仓库和\(n\)个零售商,第\(i\)个仓库送到第\(j\)个零售商需要花费\(v[i][j]\)元。现在需要让仓库的供给量以及零售商的收获量相同,问最小花费以及最大花费。

分析:

相当经典的最小费用最大流的模型。因为要保证供给以及收获相同,即代表着流量平衡,因此我们可以让超级源点\(sp\)跟对应的仓库连一条流量为\(a_i\),费用为\(0\)的边,同时让对应的零售商跟超级汇点\(ep\)连一条流量为\(b_i\),费用为\(0\)的边。而对于仓库与零售商,我们只需要将仓库和零售商之间连一条流量为无穷,费用为\(v[i][j]\)的边。

对于最小花费问题,我们只需要在上述的图中跑最小费用最大流即可。

而对于最大花费的问题,我们只需要将上述的图中的仓库与零售商的改为连一条流量为无穷,费用为\(-v[i][j]\)的边,最后在新图上跑一边最小费用最大流,而最后最小费用的相反数即是答案。

代码:

#include <bits/stdc++.h>
using namespace std;
const int maxn = 505;
const int maxm = 20005;
int head[maxn],cnt=0;
int dis[maxn],vis[maxn],sp,ep,maxflow,cost;
const int INF=0x3f3f3f3f;
struct Node{
    int to,next,val,cost;
}q[maxm<<1];
void init(){
    memset(head,-1,sizeof(head));
    cnt=2;
    maxflow=cost=0;
}
void addedge(int from,int to,int val,int cost){
    q[cnt].to=to;
    q[cnt].next=head[from];
    q[cnt].val=val;
    q[cnt].cost=cost;
    head[from]=cnt++;
}
void add_edge(int from,int to,int val,int cost){
    addedge(from,to,val,cost);
    addedge(to,from,0,-cost);
}
bool spfa(){
    memset(vis,0,sizeof(vis));
    memset(dis,0x3f,sizeof(dis));
    dis[sp]=0;
    vis[sp]=1;
    queue<int>que;
    que.push(sp);
    while(!que.empty()) {
        int x = que.front();
        que.pop();
        vis[x]=0;
        for(int i=head[x];i!=-1;i=q[i].next){
            int to=q[i].to;
            if(dis[to]>dis[x]+q[i].cost&&q[i].val){
                dis[to]=dis[x]+q[i].cost;
                if(!vis[to]){
                    que.push(to);
                    vis[to]=1;
                }
            }
        }
    }
    return dis[ep]!=0x3f3f3f3f;
}
int dfs(int x,int flow){
    if(x==ep){
        vis[ep]=1;
        maxflow+=flow;
        return flow;
    }
    int used=0;
    vis[x]=1;
    for(int i=head[x];i!=-1;i=q[i].next){
        int to=q[i].to;
        if((vis[to]==0||to==ep)&&q[i].val!=0&&dis[to]==dis[x]+q[i].cost){
            int minflow=dfs(to,min(flow-used,q[i].val));
            if(minflow!=0){
                cost+=q[i].cost*minflow;
                q[i].val-=minflow;
                q[i^1].val+=minflow;
                used+=minflow;
            }
            if(used==flow) break;
        }
    }
    return used;
}
int mincostmaxflow(){
    while(spfa()){
        vis[ep]=1;
        while(vis[ep]){
            memset(vis,0,sizeof(vis));
            dfs(sp,INF);
        }
    }
    return maxflow;
}
int a[maxn],b[maxn],v[maxn][maxn];
int main()
{
    int n,m;
    init();
    scanf("%d%d",&n,&m);
    sp=n+m+1,ep=n+m+2;
    for(int i=1;i<=n;i++){
        scanf("%d",&a[i]);
        add_edge(sp,i,a[i],0);
    }
    for(int i=1;i<=m;i++){
        scanf("%d",&b[i]);
        add_edge(i+n,ep,b[i],0);
    }
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            scanf("%d",&v[i][j]);
            add_edge(i,j+n,INF,v[i][j]);
        }
    }
    mincostmaxflow();
    printf("%d\n",cost);
    init();
    for(int i=1;i<=n;i++){
        add_edge(sp,i,a[i],0);
    }
    for(int i=1;i<=m;i++){
        add_edge(i+n,ep,b[i],0);
    }
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            add_edge(i,j+n,INF,-v[i][j]);
        }
    }
    mincostmaxflow();
    printf("%d\n",-cost);
    return 0;
}

原文地址:https://www.cnblogs.com/Chen-Jr/p/11348138.html

时间: 2024-10-06 11:48:01

luogu p4015(最小费用最大流)的相关文章

P4015 运输问题 最大/最小费用最大流

P4015 运输问题 1 #include <bits/stdc++.h> 2 using namespace std; 3 const int maxn = 205, inf = 0x3f3f3f3f; 4 struct Edge { 5 int from, to, cap, flow, cost; 6 }; 7 struct MCMF { 8 int n, m, s, t; 9 vector<Edge> edges; 10 vector<int> G[maxn];

【Luogu】P2045方格取数加强版(最小费用最大流)

题目链接 通过这题我学会了引诱算法的行为,就是你通过适当的状态设计,引诱算法按照你想要它做的去行动,进而达到解题的目的. 最小费用最大流,首先将点拆点,入点和出点连一条费用=-权值,容量=1的边,再连费用=0,容量=INF的边,跑最小费用最大流即可. #include<cstdio> #include<cctype> #include<algorithm> #include<cstring> #include<cstdlib> #include&

洛谷 P4015 运输问题 【最小费用最大流+最大费用最大流】

s向仓库i连ins(s,i,a[i],0),商店向t连ins(i+m,t,b[i],0),商店和仓库之间连ins(i,j+m,inf,c[i][j]).建两次图分别跑最小费用最大流和最大费用最大流即可. #include<iostream> #include<cstdio> #include<queue> #include<cstring> using namespace std; const int N=1000005,inf=1e9; int n,m,h

【BZOJ3876】【Ahoi2014】支线剧情 有下界的最小费用最大流

#include <stdio.h> int main() { puts("转载请注明出处谢谢"); puts("http://blog.csdn.net/vmurder/article/details/43025375"); } [BZOJ2324]营救皮卡丘 这道题也是一道有下界的最小费用最大流. 我的题解地址:http://blog.csdn.net/vmurder/article/details/41378979 这道题其实就是模板题. 我的处理

POJ 3686.The Windy&#39;s 最小费用最大流

The Windy's Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 5477   Accepted: 2285 Description The Windy's is a world famous toy factory that owns M top-class workshop to make toys. This year the manager receives N orders for toys. The ma

P3381 【模板】最小费用最大流

P3381 [模板]最小费用最大流 题目描述 如题,给出一个网络图,以及其源点和汇点,每条边已知其最大流量和单位流量费用,求出其网络最大流和在最大流情况下的最小费用. 输入输出格式 输入格式: 第一行包含四个正整数N.M.S.T,分别表示点的个数.有向边的个数.源点序号.汇点序号. 接下来M行每行包含四个正整数ui.vi.wi.fi,表示第i条有向边从ui出发,到达vi,边权为wi(即该边最大流量为wi),单位流量的费用为fi. 输出格式: 一行,包含两个整数,依次为最大流量和在最大流量情况下的

C++之路进阶——最小费用最大流(支线剧情)

F.A.Qs Home Discuss ProblemSet Status Ranklist Contest ModifyUser  hyxzc Logout 捐赠本站 Notice:由于本OJ建立在Linux平台下,而许多题的数据在Windows下制作,请注意输入.输出语句及数据类型及范围,避免无谓的RE出现. 3876: [Ahoi2014]支线剧情 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 542  Solved: 332[Submit

hdu 4494 Teamwork 最小费用最大流

Teamwork Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=4494 Description Some locations in city A has been destroyed in the fierce battle. So the government decides to send some workers to repair these location

POJ - 2195 Going Home(最小费用最大流)

1.N*M的矩阵中,有k个人和k个房子,每个人分别进入一个房子中,求所有人移动的最小距离. 2.人看成源点,房子看成汇点,求最小费用最大流. 建图-- 人指向房子,容量为1,费用为人到房子的曼哈顿距离. 建立超级源点和超级汇点:超级源点指向人,容量为1,费用为0:超级汇点指向房子,容量为1,费用为0. 求超级源点到超级汇点的最小费用最大流即可. ps:容量为什么都设为1?---有待研究.. 3. 1.Bellman-Ford: #include<iostream> #include<st