码迷,mamicode.com
首页 > 其他好文 > 详细

学习了ZKW费用流

时间:2015-06-22 14:53:34      阅读:119      评论:0      收藏:0      [点我收藏+]

标签:

所谓ZKW费用流,其实就是Dinic。

若干年前有一个人发明了最小增广路算法,每次用BFS找一条增广路,时间O(nm^2)

然后被DinicD飞了:我们为什么不可以在长度不变时多路增广呢?时间O(n^2m)

于是可以用到费用流里来:我们为什么不可以在s到t最短路不变时多路增广呢?

实现做法要从t逆向做SPFA,然后多路增广,具体可以见代码

技术分享
#include<cstdio>
#include<cctype>
#include<queue>
#include<cstring>
#include<algorithm>
#define rep(s,t) for(int i=s;i<=t;i++)
#define ren for(int i=first[x];i!=-1;i=next[i])
using namespace std;
inline int read() {
    int x=0,f=1;char c=getchar();
    for(;!isdigit(c);c=getchar()) if(c==-) f=-1;
    for(;isdigit(c);c=getchar()) x=x*10+c-0;
    return x*f;
}
const int inf=1e9;
const int maxn=310;
const int maxm=300010;
struct ZKW {
    int n,m,s,t,cost,ans;
    int d[maxn],vis[maxn],first[maxn],inq[maxn],next[maxm];
    struct Edge {int from,to,flow,cost;}edges[maxm];
    void init(int n) {
        this->n=n;m=0;
        memset(first,-1,sizeof(first));
        memset(inq,0,sizeof(inq));
    }
    void AddEdge(int from,int to,int cap,int cost) {
        edges[m]=(Edge){from,to,cap,cost};next[m]=first[from];first[from]=m++;
        edges[m]=(Edge){to,from,0,-cost};next[m]=first[to];first[to]=m++;
    }
    int BFS() {
        rep(1,n) d[i]=inf;
        queue<int> Q;Q.push(t);d[t]=0;
        while(!Q.empty()) {
            int x=Q.front();Q.pop();inq[x]=0;
            ren {
                Edge& e=edges[i^1];
                if(e.flow&&d[e.from]>d[x]+e.cost) {
                    d[e.from]=d[x]+e.cost;
                    if(!inq[e.from]) inq[e.from]=1,Q.push(e.from);
                }
            }
        }
        rep(0,m) edges[i].cost+=d[edges[i].to]-d[edges[i].from];
        cost+=d[s];return d[s]!=inf;
    }
    int DFS(int x,int a) {
        if(x==t||!a) {ans+=cost*a;return a;}
        int flow=0,f;vis[x]=1;
        ren {
            Edge& e=edges[i];
            if(e.flow&&!e.cost&&!vis[e.to]&&(f=DFS(e.to,min(e.flow,a)))) {
                e.flow-=f;edges[i^1].flow+=f;
                a-=f;flow+=f;if(!a) break;
            }
        }
        return flow;
    }
    int solve(int s,int t) {
        this->s=s;this->t=t;ans=cost=0;
        while(BFS()) do memset(vis,0,sizeof(vis));while(DFS(s,inf));
        return ans;
    }
}sol;
int main() {
    int n=read(),m=read();sol.init(n);
    rep(1,m) {
        int a=read(),b=read(),c=read(),d=read();
        sol.AddEdge(a,b,c,d);
    }
    printf("%d\n",sol.solve(1,n));
    return 0;
}
View Code

 

学习了ZKW费用流

标签:

原文地址:http://www.cnblogs.com/wzj-is-a-juruo/p/4593189.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!