zoukankan      html  css  js  c++  java
  • 洛谷3381

    最小费用最大流模板题

    思路和网络流的EK算法类似,

    1.建正向边,反向边(反向边流量为0,花费为负数:走反向边即取消上次走过后增加的值,因此如此定义)

    2.用spfa增广,找到流量大于0且由花费决定的最小dis[ t ],接着回溯,找到能通过的最大流量(minn)

    3.ansflow+=minn;anscost+=minn*dis[t];

    4.重复2.3步骤,直至无法增广,即为答案

    #include<cstdio>
    #include<cctype>
    #include<queue>
    #include<cstring>
    #include<algorithm>
    #define INF 0x33333333
    using namespace std;
    const int N=5002,M=50002;
    int n,m,s,t,cnt=-1,vis[N],dis[N],head[N];
    int pv[N],pe[N];
    struct data{int v,flow,cos,next;}edge[2*M];
    queue<int>q;
    
    inline void read(int &x){
        char ch=getchar();x=0;
        while(!isdigit(ch))ch=getchar();
        while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
    }
    
    inline bool spfa(int S,int T)
    {
        memset(dis,0x33,sizeof dis);
        memset(vis,0,sizeof vis);
        q.push(S),vis[S]=1,dis[S]=0;
        while(!q.empty())
        {
            int now=q.front();q.pop();vis[now]=0;
            for (int i=head[now];~i;i=edge[i].next)//注意不是i>0;会出现第0条边 
                if (edge[i].flow>0 && dis[edge[i].v]>dis[now]+edge[i].cos)
                {
                    dis[edge[i].v]=dis[now]+edge[i].cos;
                    pe[edge[i].v]=i,pv[edge[i].v]=now;
                    if (!vis[edge[i].v])
                        vis[edge[i].v]=1,q.push(edge[i].v);
                }
        }
        return dis[T]<INF;
    }
    
    inline void Putans(int x){
        if(x>=10)Putans(x/10);putchar(x%10+'0');
    }
    
    inline void mfmc(int S,int T){
        int Cos=0,Flow=0,minn;
        while(spfa(S,T)){
            minn=INF;
            for(int i=T;i!=S;i=pv[i])minn=min(minn,edge[pe[i]].flow);
            Cos+=minn*dis[T];
            Flow=Flow+minn;
            for(int i=T;i!=S;i=pv[i]){edge[pe[i]].flow-=minn;edge[pe[i]^1].flow+=minn;}
        }
        Putans(Flow);printf(" ");Putans(Cos);//printf("%d %d",Flow,Cos);
    }
    
    inline void insert(int u,int v,int flow,int cost){
        edge[++cnt].v=v;
        edge[cnt].flow=flow;edge[cnt].cos=cost;edge[cnt].next=head[u];head[u]=cnt;
    }
    
    int main(){
        read(n);read(m);read(s);read(t);
        memset(head,-1,sizeof(head));//一定要赋值-1,否则spfa时出现第0条边,无限循环 
        memset(edge,-1,sizeof(edge));
        for(int i=1;i<=m;i++){//tot初值为-1(保证 ^1后是反向边) 
            int u,v,flow,cost;
            read(u);read(v);read(flow);read(cost);
            insert(u,v,flow,cost);insert(v,u,0,-cost);//flow要赋值0,否则其初值为-1  
        }
        mfmc(s,t);
    }
  • 相关阅读:
    我爱Java系列之---【SpringBoot打成war包部署】
    279. Perfect Squares
    矩阵dfs--走回路
    112. Path Sum
    542. 01 Matrix
    106. Construct Binary Tree from Inorder and Postorder Traversal
    105. Construct Binary Tree from Preorder and Inorder Traversal
    Invert Binary Tree
    563 Binary Tree Tilt
    145 Binary Tree Postorder Traversal
  • 原文地址:https://www.cnblogs.com/MikuKnight/p/8888361.html
Copyright © 2011-2022 走看看