首页 > 其他分享 >网络流入门学习笔记

网络流入门学习笔记

时间:2022-09-26 18:37:16浏览次数:69  
标签:pre 流入 int ll flow 网络 笔记 while 汇点

基本概念

网络流,即网络+

网络就是由许多结点和边组成的图,在这里边权表示允许通过的最大流量

在网络中,有两个特殊的结点,一个叫源点,一个叫汇点

网络流中最大流问题可以看成是:假设在源点注入无限多的水流,最终会流到汇点的最大流量(中间有点类似木桶原理,一条完整路径上的最大流量是最小的边权。

最小割概念:在网络中选取若干条边删除,使得源点到汇点变成不连通的,而且删掉的边权之和最小。

定理:最大流在数值上等于最小割

算法

如果直接找从源点到汇点的一条路径,可能经过了边权不那么优的边
引入反向弧——每次选取 i 到 j 的一条路径中 k 的流量,给它的反向边边权赋予权值 k。
实际的意义是可以反悔。如果某条边被正反走了两次,那么可以认为这条边是没有选取的

EK算法

最基础的、不加优化的网络流算法。

时间复杂度 \(O(v*e^2)\)

每次都从 S 到 T 寻找增广路,如果找到,把答案加进 ans
直到找不到了退出

点击查看代码
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int inf = 1e9;  //可能的最大流量 
const int N = 205;
int n,m;
ll g[N][N],pre[N];
int S,T; 

ll bfs(int s,int t){  // 求s到t的一条路的流量 
	ll flow[N]={0};
	memset(pre,-1,sizeof(pre));
	flow[s] = inf;
	pre[s] = 0;
	queue<int>q;
	q.push(s);
	while(!q.empty()){
		int u = q.front();
		q.pop();
		for(int i=1;i<=n;i++){
			if(i!=s&&g[u][i]>0&&pre[i]==-1){
				pre[i] = u;
				q.push(i);
				flow[i]=min(flow[u],g[u][i]);
			}
		}
	}
	if(pre[t]==-1) return -1;
	return flow[t];
}

ll maxflow(int s,int t){
	ll Maxflow = 0;
	while(1){
		ll flow = bfs(s,t);
		if(flow==-1) break;
		int cur = t;
		while(cur!=s){  //增加反向弧 
			int father = pre[cur];
			g[father][cur] -= flow;
			g[cur][father] += flow;
			cur = father;
		}
		Maxflow += flow;
	}
	return Maxflow;
}

int main(){
	int t;
//	cin>>t;
	t=1;
	int cnt=0;
	while(t--){  // ind  1 to n    m dugs
		scanf("%d%d",&n,&m);
		scanf("%d%d",&S,&T);  //源点、汇点 
		memset(g,0,sizeof(g));
		ll w;
		for(int i=1,u,v;i<=m;i++){
			scanf("%d%d%lld",&u,&v,&w);
			g[u][v]+=w;
		} 
//		printf("Case %d: ",++cnt);
		printf("%lld\n",maxflow(S,T));
	}
	return 0;
}

ISAP算法

时间复杂度很低的优秀算法。

点击查看代码
#include<stdio.h>
#include<string.h>
#include<queue>
#include<algorithm>
#define ll long long
using namespace std;
#define inf 0x3f3f3f3f
const int maxn = 409;
ll pre[maxn],gap[maxn],h[maxn];//pre记录是从哪一条边到达i的,gap记录在i层中有几个点,h记录i点的层次。
ll firs[maxn];//邻接表建边 
struct node{
    ll  v,flow,nex;
}edge[maxn*maxn];
int N, n, m, S, T;

inline int in(int x) {
	return x;
}

inline int out(int x) {
	return x + n + 1;
}

void build_edge(int u,int v,int flow){
    edge[N]=(node){v,flow,firs[u]};
    firs[u]=N++;
    edge[N]=(node){u,0,firs[v]};
    firs[v]=N++;
}

void bfs(int s,int t)//广搜建层,不过这里是从汇点开始的,别弄错了,
{
    //初始化
    memset(h,-1,sizeof(h));
    memset(gap,0,sizeof(gap));
    queue<int>q;
    while(!q.empty())q.pop();

    q.push(t);
    h[t]=0;//将汇点定义为0层
    gap[0]=1;//0层点的个数加一
    while(!q.empty())
    {
        int u=q.front();
        q.pop();
        for(int i=firs[u];i!=-1;i=edge[i].nex)
        {
            int v=edge[i].v;
            if(h[v]==-1)
            {
                h[v]=h[u]+1;
                gap[h[v]]++;//记录当前层的个数
                q.push(v);
            }
        }
    }
}

ll isap(int s,int t,int n){
    bfs(s,t);
    memset(pre,0,sizeof(pre));//记录该点的前驱是谁(这里的前驱是指边,不是点)
    ll ans=0,d,u=s;//ans记录最大流,d记录当前路径中的最小流,u记录当前查找到哪个点了。
    while(h[s]<n)//如果源点的层小于点的个数就可能还有流
    {
        int flag=1;//判断是否能够走,能否找到流。
        if(u==s) d=inf;//如果再次从源点出发,就初始化d,
        for(int i=firs[u];i!=-1;i=edge[i].nex)
        {
            ll v=edge[i].v,flow=edge[i].flow;
            if(h[v]+1==h[u]&&flow)
            {
                pre[v]=i;//记录该点是由哪条边到达的
                u=v;//记录要去哪个点
                d=min(d,flow);//记录最小流
                flag=0;//能够往前走
                if(v==t)//如果走到了汇点
                {
                    while(u!=s)//原路返回,更新边的容量,与dinic的dfs思路一样
                    {
                        int j=pre[u];
                        edge[j].flow-=d;
                        edge[j^1].flow+=d;
                        u=edge[j^1].v;
                    }
                    ans+=d;//加上当前找到的流
                }
                break;
            }
        }
        if(flag)//如果没有找到下面的路,就更新点的层次
        {
            if(--gap[h[u]]==0) //如果该层上没有了点,说明没法继续查找了,结束。
                break;
            ll min_=n-1;
            for(int i=firs[u];i!=-1;i=edge[i].nex)//查找与u相连的最小层,
            {
                ll v=edge[i].v,flow=edge[i].flow;
                if(flow)
                    min_=min(min_,h[v]);
            }
            h[u]=min_+1;//重新给u建层
            gap[h[u]]++;//更新层的个数
            if(u!=s)//重要一步,如果当前点不是源点就要向后退一步,继续查找。
             u=edge[pre[u]^1].v;
        }
    }
    return ans;
}

int main(){
	int t; scanf("%d", &t);
	while(t--) {
	    scanf("%d%d",&n,&m);
	    memset(firs,-1,sizeof(firs));
	    N=0;
	    for(int i=1,u,v;i<=m;i++){
				scanf("%d%d",&u,&v);
				build_edge(out(u), in(v), 1);
			} 
			for(int i = 0; i <= n; i++) {
				build_edge(in(i), out(i), 1);
			}
		S = out(0);
		T = in(n);
	    n = n * 2 + 2;
	    printf("%lld\n",isap(S,T,n));
    }
	return 0;
}

例题 (待补充

标签:pre,流入,int,ll,flow,网络,笔记,while,汇点
From: https://www.cnblogs.com/re0acm/p/16731930.html

相关文章

  • EasyCode插件的使用笔记
    1插件下载2使用idea连接数据库3选择要生成代码的数据库表,右键进行操作4修改模板entity修改模板示例##导入宏定义$!{define.vm}##保存文件(宏定义)#save("/en......
  • [学习笔记]Kruskal以及Kruskal重构树
    1.\(\operatorname{Kruskal}\)最小生成树本来觉得这个没必要写但是强迫症发作只能写了qwq真实原因是我居然交了四发才过板子题可以说是人类之耻了\(\operatorname{Kru......
  • 【学习笔记】初始JQuery
    初始JQuery 了解JQueryjQuery和JavaScript的关系:jQuery相当于一个库,里面有大量的JavaScript函数和Java中的工具类差不多。 获取jQuery 官网下载[jquery.co......
  • Flink笔记
    高可用(HA):直白来说就是系统不会因为某台机器,或某个实例挂了,就不能提供服务了。高可用需要做到分布式、负载均衡、自动侦查、自动切换、自动恢复等。高吞吐:单位时间内,能......
  • Jmeter学习笔记
    安装部署直接去官网下载最新版jmeter,解压到任意目录官网地址:https://jmeter.apache.org/download_jmeter.cgi安装JDK8+(这里不再介绍步骤)配置jmeter环境变量可以在运......
  • 计算机网络物理层
    1、数据通信系统   数据通信涉及三个部分:发送,传输,接收。  DTE:dataterminalequipment,指的是计算机和终端设备(发送和接收数据的设备)DCE:datacommunications......
  • RocketMQ性能优化【实战笔记】
    转发:https://cloud.tencent.com/developer/article/1496414目录一、系统优化1.最大文件数2.系统参数调整二、RocketMQ性能调优1.开启异步刷盘2.开启堆外内存设置3......
  • TypeScript学习笔记(三)—— 编译选项、声明文件
    一、编译选项与配置文件自动编译文件编译文件时,使用-w指令后,TS编译器会自动监视文件的变化,并在文件发生变化时对文件进行重新编译。示例:tscxxx.ts-w......
  • 自然语言处理NLP(学习笔记)
       NLP的概念自然语言处理,英文NaturalLanguageProcessing,简写NLP。NLP这个概念本身过于庞大,可以把它分成“自然语言”和“处理”两部分。自然语言先来看......
  • 线段树学习笔记(基础&进阶)(一) | P3372 【模板】线段树 1 题解
    什么是线段树线段树是一棵二叉树,每个结点存储需维护的信息,一般用于处理区间最值、区间和等问题。线段树的用处对编号连续的一些点进行修改或者统计操作,修改和统计的复杂......