zoukankan      html  css  js  c++  java
  • 网络流——最大流Dinic算法

    前言

    突然发现到了新的一年什么东西好像就都不会了凉凉

    算法步骤

    1. 建残量网络图
    2. 在残量网络图上跑增广路
    3. 重复1直到没有增广路(注意一个残量网络图要尽量把价值都用完,不然会浪费建图的时间)

    代码实现

    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    #include<math.h>
    #include<algorithm>
    #include<queue>
    #include<set>
    #include<map>
    #include<iostream>
    using namespace std;
    #define ll long long
    #define re register
    #define file(a) freopen(a".in","r",stdin);freopen(a".out","w",stdout)
    inline int gi(){
    	int f=1,sum=0;char ch=getchar();
    	while(ch>'9' || ch<'0'){if(ch=='-')f=-1;ch=getchar();}
    	while(ch>='0' && ch<='9'){sum=(sum<<3)+(sum<<1)+ch-'0';ch=getchar();}
    	return f*sum;
    }
    const int N=10010,M=100010,Inf=1e9+10;
    int n,m,s,t,flow;
    class Graph{
    private:
    	int front[N],nxt[M<<1],to[M<<1],w[M<<1],cnt,dep[N];
    	bool bfs(){
    		queue<int >Q;while(!Q.empty())Q.pop();
    		memset(dep,0,sizeof(dep));
    		Q.push(s);dep[s]=1;
    		while(!Q.empty()){
    			int u=Q.front();Q.pop();
    			for(int i=front[u];i!=-1;i=nxt[i]){
    				int v=to[i];
    				if(!dep[v] && w[i]){
    					dep[v]=dep[u]+1;Q.push(v);
    				}
    			}
    		}
    		return dep[t];
    	}
    	int dfs(int u,int Flow){
    		if(u==t || !Flow)return Flow;
    		for(int i=front[u];i!=-1;i=nxt[i]){
    			int v=to[i];
    			if(dep[v]==dep[u]+1 && w[i]){
    				int di=dfs(v,min(Flow,w[i]));
    				if(di){
    					w[i]-=di;w[i^1]+=di;
    					return di;
    				}
    			}
    		}
    		return 0;
    	}
    public:
    	void Add(int u,int v,int val){to[cnt]=v;nxt[cnt]=front[u];front[u]=cnt;w[cnt]=val;cnt++;}
    	void init(){memset(front,-1,sizeof(front));cnt=0;}
    	void Dinic(){
    		while(bfs()){
    			while(int d=dfs(s,Inf)){
    				flow+=d;
    			}
    		}
    	}
    }MaxFlow;
    int main(){
    	n=gi();m=gi();s=gi();t=gi();
    	MaxFlow.init();
    	for(int i=1;i<=m;i++){
    		int u=gi(),v=gi(),val=gi();
    		MaxFlow.Add(u,v,val);MaxFlow.Add(v,u,0);
    	}
    	MaxFlow.Dinic();
    	printf("%d
    ",flow);
    	return 0;
    }
    

    当前弧优化

    考虑我们在dfs搜索的时候,是不是有什么东西重复了?
    显然搜索过的就不可能再来了(因为已经被压榨干净了)
    然后就可以修改一些dfs的过程。

    
    int dfs(int u,int Flow){
    	if(u==t || !Flow)return Flow;
    	for(int &i=cur[u];i!=-1;i=nxt[i]){
    		int v=to[i];
    		if(dep[v]==dep[u]+1 && w[i]){
    			int di=dfs(v,min(Flow,w[i]));
    			if(di){
    				w[i]-=di;w[i^1]+=di;
    				return di;
    			}
    		}
    	}
    	return 0;
    }
    void Dinic(){
    	while(bfs()){
    		for(int i=1;i<=n;i++)cur[i]=front[i];
    		while(int d=dfs(s,Inf)){
    			flow+=d;
    		}
    	}
    }
    

    优化还是比较明显的。

    大家可以在看完之后切了这道题目

    当然陆续将会推出HLPP与ISAP的总结。

  • 相关阅读:
    js&jquery避免报错的方法
    if-else用法
    js-form表单元素的自定义属性
    a标签
    jQuery知识集锦
    JDK动态代理
    hibernate之多对一单向关联
    STL算法设计理念
    计算机常识--win7 删除文件、拒绝訪问等等,所有提示权限不够 解决的方法
    大话设计模式C++实现-第8章-工厂方法模式
  • 原文地址:https://www.cnblogs.com/mleautomaton/p/10253441.html
Copyright © 2011-2022 走看看