首页 > 其他分享 >网络流

网络流

时间:2024-01-18 23:00:13浏览次数:35  
标签:idx int 网络 addE inline du dis

最大流

1.最大流

定义

自行意会。

原理

找一条 \(S-T\) 的正权路径,给里面加流量。

显然是错的,但是可以再存反边,类似一种反悔的思想。其最大流量为 \(0\)。

此处的边权皆为空余流量。

实现

EK/FF

用 DFS、BFS 打暴力。

ISAP

预处理每个点到 \(T\) 的反图最短路(实际无必要),以此分层,DFS 分配新流量。

有一些显然的优化。GAP 断层优化、当前弧优化。还有层数较小时,可以玄学少跑几次。

namespace flow{
	const int N=1e5+10,M=2e5+10;
	int h[N],ne[M],e[M],w[M],idx=1,S,T,tot,cnt[N],dis[N],cur[N];
	inline void addE(int u,int v,int x){
		ne[++idx]=h[u],h[u]=idx,e[idx]=v,w[idx]=x;
	}
	inline void add(int u,int v,int x){
		addE(u,v,x),addE(v,u,0);
	}
	inline int dfs(int u,int sum){
		if(u==T) return sum;
		int ss=0;
		for(int &i=cur[i];i;i=ne[i]){
			int v=e[i];
			if(w[i]<=0||dis[u]!=dis[v]+1) continue;
			int tmp=dfs(v,min(w[i],sum-ss));
			ss+=tmp,w[i]-=tmp,w[i^1]+=tmp;
			if(sum==ss||dis[S]>=tot) return ss;
		}
		if(!--cnt[dis[u]]) dis[S]=tot;
		++cnt[++dis[u]];
		cur[u]=h[u];
		return ss;
	}
	inline int work(){
		int res=0;
		for(int i=1;i<=tot;++i) cur[i]=h[i];
		while(dis[S]<tot) res+=dfs(S,inf);
		return res;
	}
}
using flow::S;
using flow::T;
using flow::tot;
using flow::add;
using flow::work;

注意

  • 链式前向星建图正反边一定要相邻建。

  • idx 初值要是奇数。

  • 网格图用 id[][] 数组时,一定要考虑是不是赋过值的。可以分成多个部分,不要太压行。

  • 数组大小。

建模


2.最小割

定义

分成包含 \(S\) 和 \(T\) 的两部分点,使 \(S\) 部到 \(T\) 部的边流量和最小。

原理

值等于最大流,考虑非最大流就会有未填满的路径。

实现

同最大流。

建模

  • 核心,不能有通路。

  • 网格图染色(2或4),建图。但不能一见网格图就一定是。

  • 串联=或;并联=且。

  • 点权转边权。

  • 拆点、限流。

  • 每个点分类型,有代价

  • 一组在一起有额外代价(建模同下)。

  • 每个点分类型,有贡献
  • 一组在一起有额外贡献(建模如嫖来的图,\(C_i\) 在就意味着它所连的组必须没有连向 \(T\) 的)。

i

  • 当在同一个集合有代价时,可以选择一类路径反向、交换集合边权。

  • 找边数最小最小割,增量法(乘)。


最大权闭合子图

定义

没有向外出边的点集,使其点权和最大。

原理

\(\text{正权和}-\text{最小割}\)。正权点不要会有代价,负权点要也会有代价。

实现

在原图基础上,\(S\) 向正权点连边权,负权点向 \(T\) 连边权相反数。

建模

  • 有明确带权依赖关系。

  • 二分图两边相等,一边加 inf,一边减 inf;扩倍,压缩信息。


3.费用流

定义

最值费用最大流。

原理

贪心,优先增广最短路(ISAP 当中最短路带权)。

实现

SPFA 求最短路(有负环,只走有流量的边),最短路上增广。

  • 多路增广。

可以类似 SAP,但是无优化。

细节

静态数组作队列,一定要判越界,循环使用内存。

memset 最后尽量用 sizeof,不要自己算,可以把点数开精确一点。(悲

可以动态加边。

建模

最大流满足一个限制,费用再求另一个最值。

拆点定流

还是拆点,但是不好限制每一个点刚刚好有给定的流量。考虑直接让拆出来的 \(2n\) 个点凭空获得流(当然,有代价),再通过题目条件,把流分出去,这里的“分”具有偏序关系,同一层的点也可以视情况有偏序关系。

另一道

拆点定向

网格图,只有连成环的拐弯才有权值。染色,分类。一个点分上下方向和左右方向,连两条边,一条有权,一条无权,最终减去一倍权和。相邻对应连。

  • 总的减去一部分。预先设置一些状态,再调整。

  • 拆绝对值。


4.上下界网络流

定义

每个边的流量有上下界。

可行流

定义

问有没有解。

最大/小流

定义

在满足限制下的最值。

实现

namespace udflow{
	const int N=1e5+10,M=2e6+10;
	int S,T,S1,T1,S2,T2,tot,h[N],ne[M],e[M],w[M],idx=1,cur[N],cnt[N],dis[N],exfl,du[N];
	inline void addE(int u,int v,int x){
		ne[++idx]=h[u],h[u]=idx,e[idx]=v,w[idx]=x;
	}
	inline void add(int u,int v,int l,int r){
		du[v]+=l,du[u]-=l;
		addE(u,v,r-l),addE(v,u,0);
	}
	inline int dfs(int u,int sum){
		if(u==T2) return sum;
		int ss=0;
		for(int &i=cur[u];i;i=ne[i]){
			int v=e[i];
			if(w[i]<=0||dis[u]!=dis[v]+1) continue;
			int tmp=dfs(v,min(w[i],sum-ss));
			ss+=tmp,w[i]-=tmp,w[i^1]+=tmp;
			if(sum==ss||dis[S2]>=tot) return ss;
		}
		if(!--cnt[dis[u]]) dis[S2]=tot;
		++cnt[++dis[u]];
		cur[u]=h[u];
		return ss;
	}
	inline void init(){
		memset(dis,0,sizeof dis);
		memset(cnt,0,sizeof cnt);
	}
	inline int work(){
		addE(T,S,inf),addE(S,T,0);
		int bg=idx;
		for(int i=1;i<=tot;++i){
			if(du[i]>0) addE(S1,i,du[i]),addE(i,S1,0),exfl+=du[i];
			if(du[i]<0) addE(i,T1,-du[i]),addE(T1,i,0);
		}
		for(int i=1;i<=tot;++i) cur[i]=h[i];
		int res=0;
		S2=S1,T2=T1;
		while(dis[S2]<tot) res+=dfs(S2,inf);
		if(res!=exfl) return -1;
		init();
		for(int i=1;i<=tot;++i) cur[i]=h[i];
		S2=S,T2=T;
		res=w[bg];
		w[bg]=w[bg-1]=0;
		while(dis[S2]<tot) res+=dfs(S2,inf);
		return res;
	}
}
using udflow::S;
using udflow::T;
using udflow::S1;
using udflow::T1;
using udflow::tot;
using udflow::add;
using udflow::work;

费用流

定义

区分一下最值费用最大流和单纯的费用流。

后者在增广的 dis 不优后就可以退出了。

实现

namespace udflow{
	const int N=1e5+10,M=2e6+10;
	int S,T,S1,T1,S2,T2,tot,h[N],ne[M],e[M],w1[M],w2[M],idx=1,q[N],hh,tt,sum,flow[N],pre[N],dis[N],du[N];
	bool vis[N];
	inline void addE(int u,int v,int x1,int x2){
		ne[++idx]=h[u],h[u]=idx,e[idx]=v,w1[idx]=x1,w2[idx]=x2;
	}
	inline void add(int u,int v,int l,int r,int x){
		sum+=l*x;
		du[v]+=l,du[u]-=l;
		addE(u,v,r-l,x),addE(v,u,0,-x);
	}
	inline bool spfa(){
		memset(dis,0x3f,sizeof dis);
		memset(flow,0x3f,sizeof flow);
		memset(vis,0,sizeof vis);
		hh=0,tt=1;
		q[0]=S2;
		dis[S2]=0;
		while(hh!=tt){
			int u=q[hh++];
			if(hh==N) hh=0;
			vis[u]=0;
			for(int i=h[u];i;i=ne[i]){
				int v=e[i],tmp=dis[u]+w2[i];
				if(w1[i]>0&&dis[v]>tmp){
					dis[v]=tmp;
					flow[v]=min(flow[u],w1[i]);
					pre[v]=i^1;
					if(!vis[v]){
						vis[v]=1;
						q[tt++]=v;
						if(tt==N) tt=0;
					}
				}
			}
		}
		return dis[T]<inf;
	}
	inline int work(){
		addE(T,S,inf,0),addE(S,T,0,0);
		for(int i=1;i<=tot;++i){
			if(du[i]>0) addE(S1,i,du[i],0),addE(i,S1,0,0);
			if(du[i]<0) addE(i,T1,-du[i],0),addE(T1,i,0,0);
		}
		int res=sum;
		S2=S1,T2=T1;
		while(spfa()){
			res+=dis[T2]*flow[T2];
			for(int i=T2;i!=S2;i=e[pre[i]]){
				w1[pre[i]]+=flow[T2];
				w1[pre[i]^1]-=flow[T2];
			}
		}
		return res;
	}
}
using udflow::S;
using udflow::T;
using udflow::S1;
using udflow::T1;
using udflow::tot;
using udflow::add;
using udflow::addE;
using udflow::work;

标签:idx,int,网络,addE,inline,du,dis
From: https://www.cnblogs.com/mRXxy0o0/p/17973634

相关文章

  • 人工智能与网络安全结合的思考
    一、人工智能时代的网络安全网络攻击越来越多样化、智能化、隐蔽性越来越高、危害性越来越大 二、人工智能与网络安全结合的可能性1.信息检索:面对大量日志数据处理,AI的算力能够提前发现潜在威胁,进行漏洞自动挖掘;NLP技术能够帮助用户自动提取威胁情报。2.安全性分析:分析网络......
  • 网络流
    #1模板基础最大流(最小割)constintMAXN=5e5+5,MAXM=6e5+5;structE{intnxt,to,w;}e[MAXM];inthead[MAXN],cur[MAXN];intcnt=1;voidadd(intu,intv,intw){ e[++cnt]={head[u],v,w};head[u]=cnt; e[++cnt]={head[v],u,0};head[v]=cnt;}intdis[MAXN];constintIN......
  • Wireshark网络工具是什么?
    Wireshark是网络包分析工具。网络包分析工具的主要作用是尝试捕获网络包,并尝试显示包的尽可能详细的情况。Wireshark是一个免费开源软件,不需要付费,免费使用,可以直接登陆到Wireshark的官网下载安装。在windows环境中,Wireshark使用WinPCAP作为接口,直接与网卡进行数据报文交换,这个工具......
  • 克魔助手抓包教程:网络数据包分析利器
    摘要本文详细介绍了克魔助手(Komoxo)的下载安装、抓包示例、过滤器使用以及TCP三次握手分析等内容。通过丰富的代码案例演示和详细的操作步骤,帮助读者快速掌握克魔助手的使用方法。引言克魔助手是一款流行的网络封包分析软件,广泛应用于开发测试过程中的网络数据包定位与分析。本......
  • 轻量化CNN网络 - ShuffleNet
    1.ShuffleNetV1论文:ShuffleNet:AnExtremelyEfficientConvolutionalNeuralNetworkforMobileDevices网址:https://arxiv.org/abs/1707.01083提出了``ChannelShuffle`的思想,在ShuffleUnit中全是GConv和DWConv。GConv虽然能够减少参数与计算量,但GConv中不同组之间信......
  • 网络授时服务器 时钟同步服务器 gps时钟授时系统
    随着计算机网络规模的不断扩大,各种关键业务越来越多,口令保护、加密、电子认证等安全措施也日益显得重要,许多重要的安全措施都与时间有关。比如电子认证服务就要求加密证书的用户密码须严格与时间标记对应,该证书只在特定的时间窗口内有效,因此在该时间窗内,客户机的时间必须与服务器......
  • 腊八万事“粥”全,智安网络为您云安全保驾护航
    ......
  • Fetch方法——一种简单合理的跨网络异步获取资源方式
    FetchAPI是一个JavaScript接口,用于访问和操纵HTTP管道的一些具体部分,例如请求和响应。FetchAPI提供了一个全局fetch()方法,一种简单,合理的来跨网络异步获取资源的方式。一个基本的fetch请求:fetch("http://localhost:4000/datas.json",{method:"POST",......
  • 网络编程进阶
    网络编程进阶1.OSI7层模型OSI的7层模型对于大家来说可能不太好理解,所以我们通过一个案例来讲解:假设,你在浏览器上输入了一些关键字,内部通过DNS找到对应的IP后,再发送数据时内部会做如下的事:应用层:规定数据的格式。"GET/s?wd=你好HTTP/1.1\r\nHost:www.baidu.com\r\n\r......
  • 网络编程初识
    网络编程1.网络架构1.1交换机别人想和你的电脑相互连接然后进行资源的共享,此时就需要一个设备【二层交换机】组件一个局域网。当电脑接入交换机之后,我们需要为每台电脑分配一个IP,例如:-电脑1:192.168.10.1-电脑2:192.168.10.2-电脑3:192.168.10.3-电脑......