网络流&费用流总结

来源:互联网 发布:学习ios软件 编辑:程序博客网 时间:2024/05/18 02:17

最近鸭梨山大啊,天天搞这个搞那个什么都不会,趁着闲赶紧xjb整理一波。

一.网络流

1.概念什么的自行百度吧QAQ,就不赘述了。

2.现在主要写的都是dinic,原理是不断地建立分层图增广,好用跑得快美滋滋QAQ,还有什么ISAP,SAP什么的回头再说吧QAQ

3.网络流重在建图,我现在其实也不太会QAQ,这里贴一个dinic模版,不会的照着模版抄十遍就会了

贴上代码:

int dfs(int x,int f){if(x == T) return f;int used = 0, flow;for(int i = head[x]; i; i = next[i]){if(dis[to[i]] == dis[x] + 1 && w[i] && flow = dfs(e[i].to,min(w[i],f-used))){used += flow;w[i] -= flow;w[i^1] += flow;if(f == used) return f;}}if(!used)dis[x] = -1;return used;}bool bfs(){memset(dis,0,sizeof(dis));dis[S] = 1; q.push(S);while(!q.empty()){int u = q.front(); q.pop();for(int i = head[i]; i; i = next[i]){if(w[i]&&!dis[to[i]]){dis[to[i]] = dis[u] + 1;q.push(to[i]);}}}return mark[T] > 0;}void dinic(){int ans = 0;while (bfs())  ans += dfs(1,0x7fffffff);printf("%d",ans);}
模版题很多,其中不得不提的是 草地排水(滑稽)还有很多很多....

二.费用流

1.听说就是在最大流的基础上塞进去一个费用,但是看着好不眼熟啊QAQ

2.算法实现

费用流的算法很多,但™都太难了,这里只提几种QAQ

(1)spfa算法

在最大流的基础上,以费用为边权跑spfa,至于为什么不能用dijkstra,当然是因为spfa能处理负边权我们每次都以费用为边权跑最短路,选择路上流量最小的边的流量计算答案并且更新残量网络,重复直到找不到到汇点的路径。但是这样子效率会很低QAQ,我们需要xjb加一些优化,slf(small label first)优化,也很简单就一行:我们准备加入一个点的时候把它的距离和下一个将要出队的点的距离比一下,如果它的d比较小,那么就插到队首,提前计算,否则照常插到队尾。看似很简单的一个小优化,但其实效率提升是很显著的(已在下方模版中实现)

贴上代码:

#include<iostream>#include<cstdio>#include<cstring>#include<queue>#define S 0#define T n+1#define MAXN 3000#define INF 2000000using namespace std;inline int read(){    int  x=0,f=1;char ch=getchar();    while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}    while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();}    return x*f;}int q[2000005],top,tail;int ans=0;int from[MAXN+5];int d[MAXN+5];bool mark[MAXN+5];int head[MAXN+5];int n,m,cnt=1;struct edge{    int from,w,to,next,c;}e[2000005]; void ins(int f,int t,int w,int c){    e[++cnt].next=head[f];head[f]=cnt;    e[cnt].to=t; e[cnt].w=w;e[cnt].c=c;e[cnt].from=f;} void insw(int f,int t,int w,int c){ins(f,t,w,c);ins(t,f,0,-c);}bool spfa(){    for(int i=1;i<=T;i++)d[i]=INF;    top=tail=4000;q[top]=S;mark[S]=1;d[S]=0;    while(top>=tail)    {        int u=q[tail++];        for(int i=head[u];i;i=e[i].next)        if(e[i].w&&d[u]+e[i].c<d[e[i].to])        {            d[e[i].to]=d[u]+e[i].c;from[e[i].to]=i;            if(!mark[e[i].to])            {                if(d[e[i].to]<d[q[tail]]) q[--tail]=e[i].to;                else q[++top]=e[i].to; mark[e[i].to]=1;            }                }            mark[u]=0;    }    return d[T]!=INF;}void mcf(){    int minn=INF;    for(int i=from[T];i;i=from[e[i].from])        minn=min(minn,e[i].w);    for(int i=from[T];i;i=from[e[i].from])    {        ans+=e[i].c*minn;        e[i].w-=minn;e[i^1].w+=minn;        }} int main(){    n=read();m=read();    for(int i=1;i<=m;i++)    {        int f=read(),t=read(),w=read(),c=read();        insw(f,t,w,c);        }       while(spfa())mcf();    printf("%d",ans);    return 0;}

(2)ZKW费用流

%%%ZKW神犇,强啊,zkw算法一如既往的神,效率很高,但我不会QAQ,挖坑待填。

(3)Primal-Dual 原始对偶算法

没学过,挖坑待填

(4)消圈算法

挖坑待填QAQ

例题:

(1)POJ 2195 Going Home 裸题

(2)bzoj 1070 修车

(3)bzoj 1221 软件开发

从原理上分析,在二分图和费用小的图上,zkw可以说是稳胜另外两个算法,但在距离远,费用大的情况下不如原始对偶和spfa算法。原始对偶算法则弥补了zkw的不足。无论是什么图,spfa都不是特别让人满意。

三.有上下界网络流

根本没学过,挖坑待填QAQ



原创粉丝点击