• 费用流模板


    最小费用最大流模板

    SPFA单路增广

    #include<bits/stdc++.h>
    
    using namespace std;
    typedef long long ll;
    #define inf 1000000
    #define mem(a,b) memset(a,b,sizeof(a))
    const int N=5000+20;
    const int M=50000+20;
    
    int top;//当前边下标
    int dis[N],pre[N];//源点到点i的最小距离,pre[i]记录前驱
    bool vis[N];//标记数组
    int maxflow;
    int first[N];//存储头结点
    struct Edge{
        int v,next;
        int cap,flow,cost;
    } E[M*2];
    
    void init()
    {
        mem(first,-1);
        top=0;
        maxflow=0;
    }
    void add_edge(int u,int v,int c,int cost)
    {
        E[top].v=v;
        E[top].cap=c;
        E[top].flow=0;
        E[top].cost=cost;
        E[top].next=first[u];
        first[u]=top++;
    }
    void add(int u,int v,int c,int cost)
    {
        add_edge(u,v,c,cost);
        add_edge(v,u,0,-cost);
    }
    bool spfa(int s,int t,int n)
    {
        int i,u,v;
        queue<int>q;
        mem(vis,false);
        mem(pre,-1);
        for(int i=1; i<=n; i++) dis[i]=inf;
        vis[s]=true;
        dis[s]=0;
        q.push(s);
        while(!q.empty())
        {
            u=q.front();
            q.pop();
            vis[u]=false;
            for(int i=first[u]; i!=-1; i=E[i].next)
            {
                v=E[i].v;
                if(E[i].cap>E[i].flow&&dis[v]>dis[u]+E[i].cost)
                {
                    dis[v]=dis[u]+E[i].cost;
                    pre[v]=i;
                    if(!vis[v])
                    {
                        q.push(v);
                        vis[v]=true;
                    }
                }
            }
        }
        if(dis[t]==inf)
            return false;
        return true;
    }
    int MCMF(int s,int t,int n)//minCostMaxFlow
    {
        int d;
        int i,mincost=0;//maxflow当前最大流量,mincost当前最小费用
        while(spfa(s,t,n))//表示找到了从s到t的最小费用路
        {
            d=inf;
            for(int i=pre[t]; i!=-1; i=pre[E[i^1].v]) //遍历反向边
                d=min(d,E[i].cap-E[i].flow);
            maxflow+=d;//更新最大流
            for(int i=pre[t]; i!=-1; i=pre[E[i^1].v]) //增广路上正向边流量+d,反向边流量-d
            {
                E[i].flow+=d;
                E[i^1].flow-=d;
            }
            mincost+=dis[t]*d;//dis[t]为该路径上单位流量费用之和
        }
        return mincost;
    }
    int main()
    {
        int n,m,st,ed;
        int u,v,w,c;
        scanf("%d%d%d%d",&n,&m,&st,&ed);
        init();
        for(int i=1; i<=m; i++)
        {
            scanf("%d%d%d%d",&u,&v,&w,&c);
            add(u,v,w,c);
        }
        int mincost=MCMF(st,ed,n);
        printf("%d %d
    ",maxflow,mincost);
        return 0;
    }
    
  • 相关阅读:
    端口映射到公网工具
    C# app.config文件配置和修改
    C#基本知识点-Readonly和Const的区别
    C#知识点-StopWatch-计时
    python with open as f写中文乱码
    程序员不要去这样的公司
    关于老系统的重构和优化选择
    .Net Remoting 调用远程对象
    自定义的Config节点及使用
    前台线程和后台线程区别与使用技巧
  • 原文地址:https://www.cnblogs.com/solvit/p/11453021.html
Copyright © 2020-2023  润新知