zoukankan      html  css  js  c++  java
  • 并不对劲的费用流

    最小费用最大流肯定要保证最大流,所以它和最大流有一些类似的性质。如果把费用看成边,就可以每次走最短路(保证费用最小),走到不能走为止(保证最大流)。费用流版的ek就是这样。需要注意的是,反向弧的边权为它对应的正向弧的费用的相反数,所以最短路要用spfa来求。

    费用流版的dinic,又叫zkw费用流,还是多路增广的思想。

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cstdlib>
    #include<cmath>
    #include<iomanip>
    #include<queue>
    #define maxn 5010
    #define maxm 100010
    using namespace std;
    int fir[maxn],nxt[maxm],v[maxm],fl[maxm],w[maxm],cnt;
    int n,m,dis[maxn],s,t,inf[5],mincost,maxflow;
    int p[maxn],flp[maxn],kp[maxn];
    bool vis[maxn];
    
    int read()
    {
         int x = 0, f = 1;
         char c = getchar();
         while (!isdigit(c)) 
         {
             if (c == '-') f = -1;
             c = getchar();
        }
        while(isdigit(c)) x = x*10 + c - '0', c = getchar();
         return x*f;
    }
    
    void addedge(int u1,int v1,int fl1,int w1)
    {
        v[cnt]=v1,w[cnt]=w1,fl[cnt]=fl1,nxt[cnt]=fir[u1],fir[u1]=cnt++;
        v[cnt]=u1,w[cnt]=-w1,fl[cnt]=0,nxt[cnt]=fir[v1],fir[v1]=cnt++;
    }
    
    bool spfa()
    {
        memset(dis,0x7f,sizeof(dis));
        memset(vis,0,sizeof(vis));
        queue<int>q;
        dis[s]=0;
        vis[s]=1;
        flp[s]=inf[0];
        q.push(s);
        while(!q.empty())
        {
            int u=q.front();q.pop();
            for(int k=fir[u];k!=-1;k=nxt[k])
            {
                int vv=v[k];
                if(fl[k]>0)
                {
                    if(dis[vv]>dis[u]+w[k])
                    {
                        dis[vv]=dis[u]+w[k];
                        if(!vis[vv])q.push(vv);
                        p[vv]=u;
                        kp[vv]=k;
                        flp[vv]=min(flp[u],fl[k]);
                        vis[vv]=1;
                    }
                }
            }
            vis[u]=0;
        }
        return dis[t]==inf[0]?0:1;
    }
    
    void dfs()
    {
        for(int i=t;i!=s;i=p[i])
        {
            mincost+=w[kp[i]]*flp[t];
            fl[kp[i]]-=flp[t];
            fl[kp[i]^1]+=flp[t];
        }
        maxflow+=flp[t];
        return;
    }
    int main()
    {
        memset(fir,-1,sizeof(fir));
        memset(inf,0x7f,sizeof(inf));
        n=read(),m=read(),s=read(),t=read();
        for(int i=1;i<=m;i++)
        {
            int x=read(),y=read(),z=read(),k=read();
            addedge(x,y,z,k);
        }
        while(spfa())dfs();
        cout<<maxflow<<" "<<mincost;
    }
    ek
    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cstdlib>
    #include<cmath>
    #include<iomanip>
    #include<queue>
    #define maxn 5010
    #define maxm 100010
    using namespace std;
    int fir[maxn],nxt[maxm],v[maxm],fl[maxm],w[maxm],cnt;
    int n,m,dis[maxn],s,t,inf[5],mincost,maxflow;
    bool vis[maxn];
    queue<int >q;
    int read()
    {
         int x = 0, f = 1;
         char c = getchar();
         while (!isdigit(c)) 
         {
             if (c == '-') f = -1;
             c = getchar();
        }
        while(isdigit(c)) x = x*10 + c - '0', c = getchar();
         return x*f;
    }
    
    void addedge(int u1,int v1,int fl1,int w1)
    {
        v[cnt]=v1,w[cnt]=w1,fl[cnt]=fl1,nxt[cnt]=fir[u1],fir[u1]=cnt++;
        v[cnt]=u1,w[cnt]=-w1,fl[cnt]=0,nxt[cnt]=fir[v1],fir[v1]=cnt++;
    }
    
    bool spfa()
    {
        memset(dis,0x7f,sizeof(dis));
        memset(vis,0,sizeof(vis));
        dis[t]=0;
        vis[t]=1;
        q.push(t);
        while(!q.empty())
        {
            int u=q.front();q.pop();
            for(int k=fir[u];k!=-1;k=nxt[k])
            {
                if(fl[k^1]>0)
                {
                    if(dis[v[k]]>dis[u]-w[k])
                    {
                        dis[v[k]]=dis[u]-w[k];
                        if(!vis[v[k]]){q.push(v[k]);}
                        vis[v[k]]=1;
                    }
                }
            }
            vis[u]=0;
        }
        while(!q.empty())q.pop();
        return dis[s]==inf[0]?0:1;
    }
    
    int dfs(int u,int nowflow)
    {
        if(u==t || nowflow==0)return nowflow;
        vis[u]=1;
        int sum=0,tmp;
        for(int k=fir[u];k!=-1;k=nxt[k])
        {
            if(nowflow<=0)break;
            if(fl[k]>0 && dis[v[k]]+w[k]==dis[u] && vis[v[k]]==0
            && (tmp=dfs(v[k],min(fl[k],nowflow)))>0)
            {
                nowflow-=tmp;
                sum+=tmp;
                fl[k]-=tmp;
                fl[k^1]+=tmp;
                mincost+=tmp*w[k];
            }
        }
        vis[u]=0;
        return sum;
    }
    int main()
    {
        memset(fir,-1,sizeof(fir));
        memset(inf,0x7f,sizeof(inf));
        n=read(),m=read(),s=read(),t=read();
        for(int i=1;i<=m;i++)
        {
            int x=read(),y=read(),z=read(),k=read();
            addedge(x,y,z,k);
        }
        while(spfa())
        {
            memset(vis,0,sizeof(vis));
            maxflow+=dfs(s,inf[0]);
        }
        cout<<maxflow<<" "<<mincost;
    }
    dinic
  • 相关阅读:
    Java自学第十天
    Java自学第九天
    Java自学第八天
    Java自学第七天
    Java自学第六天
    Java自学第五天
    Java自学第四天
    Java自学第三天
    Oracle11g RAC单节点重启
    PostgreSQL 日志处理
  • 原文地址:https://www.cnblogs.com/xzyf/p/8317231.html
Copyright © 2011-2022 走看看