zoukankan      html  css  js  c++  java
  • 最小费用最大流

    传送门

    这里详(jian)细(dan)解释一下最小费用最大流。
    最大流会不会?
    会!
    最短路会不会?
    会!
    那你不就会这个题怎么写了。。。
    算了,最小费用最大流是要求在最小费用的前提下求最大流,那么我们显然要优先考虑最小费用吗,想想我们求最大流的过程。
    我们就可以将费用定成边权,将bfs求增广路变成最短路求增广路,这样就能保证最小费用了,剩下的不就是最大流的事了吗?
    zkw费用流

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    int tmp=1,sum,n,m,son[200001],ans,nex[200001],h[200001],v[200001],s,t,c[200001],dis[200001],slack[200001];
    bool used[200001];
    const int inf=1e9;
    void ins(int x,int y,int z,int d)
    {
        son[++tmp]=y;nex[tmp]=h[x];h[x]=tmp;v[tmp]=d;c[tmp]=z;
        son[++tmp]=x;nex[tmp]=h[y];h[y]=tmp;v[tmp]=-d;c[tmp]=0;
    }
    int KM(int x,int flow)
    {
        if(x==t){sum+=flow*dis[t];return flow;}
        used[x]=1;
        int cp=flow;
        for(int i=h[x];i;i=nex[i])
        {
            int l=son[i];
            if(!used[l]&&c[i])
            {
                if(dis[x]+v[i]-dis[l]==0)
                {
                    int y=KM(l,min(c[i],cp));
                    cp-=y,c[i]-=y,c[i^1]+=y;
                    if(!cp)return flow;
                }
                else slack[l]=min(slack[l],dis[x]+v[i]-dis[l]);
            }
        }
        return flow-cp;
    }
    bool dfs()
    {
        int mx=inf;
        for(int i=1;i<=n;i++)
            if(!used[i])mx=min(mx,slack[i]),slack[i]=inf;
        if(mx==inf)return 1;
        for(int i=1;i<=n;i++)
            if(!used[i])dis[i]+=mx;
        return 0;
    }
    int main()
    {
        scanf("%d%d%d%d",&n,&m,&s,&t);
        for(int i=1,x,y,z,w;i<=m;i++)
        {
            scanf("%d%d%d%d",&x,&y,&z,&w);
            ins(x,y,z,w);
        }
        memset(slack,63,sizeof(slack));
        do{
            do{
            	memset(used,0,sizeof(used));
          	    tmp=KM(s,inf),ans+=tmp;
          	  }while(tmp);
            }while (!dfs());
        printf("%d %d",ans,sum);
    }
    

    EK

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<queue>
    using namespace std;
    inline void read(int &x) {
        char ch; bool ok;
        for(ok=0,ch=getchar(); !isdigit(ch); ch=getchar()) if(ch=='-') ok=1;
        for(x=0; isdigit(ch); x=x*10+ch-'0',ch=getchar()); if(ok) x=-x;
    }
    #define min(a,b) (a<b?a:b)
    #define rg register
    queue<int>q;int n,m,s,t,num,b[200001],c[200001],pre[200001],dis[100010],nxt[200001],h[100010],v[200001],w[200001],cnt=1,inf=1e9,ans,que[200001];bool vis[100010];
    inline void add(int x,int y,int z,int u)
    {
        pre[++cnt]=y,nxt[cnt]=h[x],h[x]=cnt,v[cnt]=z,w[cnt]=u,
        pre[++cnt]=x,nxt[cnt]=h[y],h[y]=cnt,v[cnt]=0,w[cnt]=-u;
    }
    bool spfa(int s)
    {
        memset(dis,63,sizeof dis);
        q.push(s),dis[s]=0;
        while(!q.empty())
        {
            int x=q.front();q.pop(),vis[x]=0;
            for(rg int i=h[x];i;i=nxt[i])
                if(v[i]&&dis[pre[i]]>dis[x]+w[i])
                {
                    dis[pre[i]]=dis[x]+w[i],b[pre[i]]=x,c[pre[i]]=i;
                    if(!vis[pre[i]])vis[pre[i]]=1,q.push(pre[i]);
                }
        }
        return dis[t]<inf;
    }
    int getans()
    {
        int mn=inf;
        for(rg int i=t;i!=s;i=b[i])mn=min(v[c[i]],mn);
        for(rg int i=t;i!=s;i=b[i])v[c[i]]-=mn,v[c[i]^1]+=mn;
        num+=mn;
        return dis[t]*mn;
    }
    int main()
    {
        read(n),read(m),read(s),read(t);
        for(rg int i=1,x,y,z,w;i<=m;i++)read(x),read(y),read(z),read(w),add(x,y,z,w);
        while(spfa(s))ans+=getans();
        printf("%d %d
    ",num,ans);
    }
    
  • 相关阅读:
    SQLalchemy 字段类型
    爬虫学习
    Linux了解一下
    django-rest-framework
    vue相关理论知识
    Django认证系统
    Form组件
    JS之AJAX
    Django之中间件
    Django之ORM
  • 原文地址:https://www.cnblogs.com/lcxer/p/10223514.html
Copyright © 2011-2022 走看看