重口味费用流

听说zkw比KM跑稠密图快很多

过来学习一个zkw继线段树后又一神作——zkw费用流

(虽然zkw线段树我还只会打模板orz)

其实就是利用了最短路的性质

dis[u]<=val(u,v)+dis[v]    当u在最短路上的时候取等号

修改dis值,即是将所有在增广路上的点u的dis加上一个delt,

而delt=min(dis[v]+w(u,v)-dis[u]) 其中u在增广路上,v不在.

和KM 一样,这样至少会多使一条边可增广,且不会破坏最短路的性质.

但其实就是背背背啊= =

树链剖分就是背背背

如今又要背背背

Orz

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
using namespace std;
const int maxn=200010;
int ans;//此处ans保存费用
int n,m,s,t;
int first[maxn],to[maxn],next[maxn],caps[maxn],cost[maxn],cnt=-1;
int vis[maxn],dis[maxn];
deque<int> dq;
inline void add(int u,int v,int w,int c)
{
    to[++cnt]=v;
    next[cnt]=first[u];
    first[u]=cnt;
    caps[cnt]=w;
    cost[cnt]=c;
}
inline int afps(int s,int t)//反向spfa 
{
    memset(vis,0,sizeof(vis));
    memset(dis,127,sizeof(dis));
    dis[t]=0;vis[t]=1;
    //deque<int> dq;
    dq.clear();
    dq.push_back(t);
    while(!dq.empty())
    {
        int now=dq.front();dq.pop_front();
        for(int i=first[now];i>-1;i=next[i])
            if(caps[i^1] && dis[to[i]]>dis[now]-cost[i])
            {
                dis[to[i]]=dis[now]-cost[i];
                if(!vis[to[i]])
                {
                    vis[to[i]]=1;
                    if(!dq.empty() && dis[to[i]]<dis[dq.front()])dq.push_front(to[i]);
                    else dq.push_back(to[i]);
                }
            }
        vis[now]=0;
    }
    return dis[s]<2139062143;
}
inline int dfs(int u,int flow)
{
    if(u==t){vis[t]=1;return flow;}
    int used=0,tmp;vis[u]=1;
    for(int i=first[u];i>-1;i=next[i])
        if(!vis[to[i]] && caps[i] && dis[u]-cost[i]==dis[to[i]])
        {
            tmp=dfs(to[i],min(caps[i],flow-used));
            if(tmp)ans+=tmp*cost[i],caps[i]-=tmp,caps[i^1]+=tmp,used+=tmp;
            if(used==flow)break;
        }
    return used;
}
inline int zkw()
{
    int maxflow=0;
    while(afps(s,t))
    {
        vis[t]=1;
        while(vis[t])
        {
            memset(vis,0,sizeof(vis));
            maxflow+=dfs(s,2139062143);
        }    
    } 
    return maxflow;
}
int main()
{
    memset(next,-1,sizeof next);memset(first,-1,sizeof first);
    scanf("%d%d%d%d",&n,&m,&s,&t);
    for(int i=1;i<=m;i++){
        int x,y,z,zz;
        scanf("%d%d%d%d",&x,&y,&z,&zz);
        add(x,y,z,zz);
        add(y,x,0,-zz);
    }
    printf("%d ",zkw());printf("%d",ans);
}
View Code
原文地址:https://www.cnblogs.com/Kong-Ruo/p/7943379.html