zoukankan      html  css  js  c++  java
  • 网络流

    我来透彻网络流了。因为懒得打字参考了LNOI创始人的博客qwq。说白了就是粘

    网络流

    网络流定义

    在一个有向图上选择一个源点,一个汇点,每一条边上都有一个流量上限(以下称为容量),即经过这条边的流量不能超过这个上界,同时,除源点和汇点外,所有点的入流和出流都相等,而源点只有流出的流,汇点只有汇入的流。

    这样的图叫做网络流。

    网络流相关定义

    1. 源点:有(n)个点,有(m)条有向边,有一个点很特殊,只出不进,叫做源点。

    2. 汇点:另一个点也很特殊,只进不出,叫做汇点。

    3. 容量和流量:每条有向边上有两个量,容量和流量,从i到j的容量通常用(c[i,j])表示,流量则通常是(f[i,j])
      通常可以把这些边想象成道路,流量就是这条道路的车流量,容量就是道路可承受的最大的车流量。
      很显然的,流量(leq)容量。而对于每个不是源点和汇点的点来说,可以类比的想象成没有存储功能的货物的中转站,所有“进入”他们的流量和等于所有从他本身“出去”的流量。

    4. 最大流:把源点比作工厂的话,问题就是求从工厂最大可以发出多少货物,是不至于超过道路的容量限制,也就是,最大流。

    增广路算法

    该方法通过寻找增广路来更新最大流,有(EK,dinic,SAP,ISAP)主流算法。

    最常用的就是(dinic)

    但是费用流需要用到(EK),所以要学会(EK)(dinic)算法;

    增广路:在图中若经过一条从源点到汇点的路径后,路径上所有边的剩余容量都(>0)(注意是(>)不是(geq)),那么这条路径被称为增广路。

    我们通过找到增广路来求解最大流,因为只要有增广路,你的所求最大流就是不最大的,当无增广路之后,最大流就求出来了读者自证不难

    dinic

    #include <bits/stdc++.h>
    using namespace std;
    
    const int maxn(210), maxm(5010);
    
    int n, m, s, t, cnt = 1, head[maxn], dep[maxn], cur[maxn];
    long long ans;
    
    struct edge{
    	int x, y, z, nxt;
    }e[maxm<<1];
    
    inline void add_edge(int x, int y, int z){
    	++cnt;
    	e[cnt].x = x, e[cnt].y = y, e[cnt].z = z;
    	e[cnt].nxt = head[x];
    	head[x] = cnt;
    	return;
    }
    
    bool bfs(){
    	for(int i = 1; i <= n; i ++) dep[i] = 0;
    	queue<int> q;
    	q.push(s);
    	dep[s] = 1;
    	while(q.size()){
    		int now = q.front();
    		q.pop();
    		for(int i = head[now]; i; i = e[i].nxt){
    			int to = e[i].y, len = e[i].z;
    			if(len and !dep[to]){
    				dep[to] = dep[now] + 1;
    				q.push(to);
    				if(to == t) return 1;
    			}
    		}
    	}
    	return 0;
    }
    
    int dfs(int now, int num){
    	if(now == t) return num;
    	int res = num;
    	for(int i = cur[now]; i and res; i = e[i].nxt){
    		cur[now] = i;
    		int to = e[i].y, len = e[i].z;
    		if(len and (dep[to] == dep[now] + 1)){
    			int k = dfs(to, min(res, len));
    			if(!k) dep[to] = 0;
    			e[i].z -= k, e[i^1].z += k, res -= k;
    		}
    	}
    	return num-res;
    }
    
    void dinic(long long &ans){
    	while(bfs()){
    		for(int i = 1; i <= n; i ++) cur[i] = head[i];
    		int num = 0;
    		while(num = dfs(s,1<<29)) ans += num;
    	}
    	return;
    }
    
    signed main(){
    	scanf("%d%d%d%d", &n, &m, &s, &t);
    	for(int x, y, z; m; m --){
    		scanf("%d%d%d", &x, &y, &z);
    		add_edge(x,y,z);
    		add_edge(y,x,0);
    	}
    	dinic(ans);
    	printf("%lld", ans);
    	return 0;
    }
    
    
  • 相关阅读:
    Android 中adb 命令(实用)
    Mac安装Scala
    使用阿里云镜像maven管理配置开发环境
    Nginx学习笔记3--Nginx和PHP(fastCGI)的配置和优化
    《实战Nginx》读书笔记--Nginx配置文件
    《实战Nginx》读书笔记
    PHP解码unicode编码中文字符代码
    yii学习笔记--使用gii快速创建控制器和模型
    yii学习笔记--配置文件的配置
    yii学习笔记--快速创建一个项目
  • 原文地址:https://www.cnblogs.com/Vanyun/p/13347891.html
Copyright © 2011-2022 走看看