首页 > 其他分享 >最小割树学习笔记

最小割树学习笔记

时间:2023-03-22 13:23:03浏览次数:48  
标签:个点 int 最小 笔记 leq 条边 割树

前言

最小割树(Gomory-Hu Tree)通过分治的思想,将图中的最小割关系建成一棵带权了树上问题。它的主要用途是求解全源最小割 / 最大流。

前置知识:

  • 一种快速的最大流算法(Dinic/ISAP 均可,FF/EK 不行,HLPP 虽然快但不方便求最小割树),本文中采用 Dinic。
  • 最小割最大流定理:最小割=最大流
  • 分治思想

下文中若无例外,均用 \(O(\text{maxflow}(n,m))\) 表示求一个 \(n\) 个点 \(m\) 条边的图上任意两点之间的最大流 / 最小割的时间复杂度。

建立

首先我们将全图看成一个集合。然后我们任选两个点 \(s,t\) 跑一遍最大流。

然后你会发现,我们可以通过源点是否与其连通分成两个集合一条权为最大流流量的边。

然后将两个集合分治,重复上述操作,直到只剩下一个点为止。

这样子我们就建出了一个最小割树(因为本来一个节点的所有子树就互不连通,所以这一定是一棵树)。

(但是我们一般都不把这棵树真的建出来,为什么呢,请看下文)。

性质

最小割树的重要性质:任意两个点的最小割等于这两个点在最小割树上的路径上的最小值。

为什么呢?因为我们的最小割树的最小割和原来的图的最小割是等价的(因为我们建树的时候就是按照最小割性质建的)而树上最小割显然是路径最小值。

于是读者可能会考虑使用 倍增 / 树链剖分去解决。但是由于最大流复杂度本身过大,因此我们甚至可以暴力算出全源最小割,最后 \(O(1)\) 回答询问。

具体来说,分治时跨集合的两个点 \(u,v\) 的最小割 \(i(u,v)\) (也就是路径最小值)可以在心中脑补出来。它只和三部分有关:\(u\to s,s\to t,t\to v\)(出来,跨子树代价,进去)。我们对这三部分的最小割取最小值即可。

代码实现

重要的事情说三遍:注意退流!注意退流!注意退流!

void GomoryHu(int l,int r){
	if(l==r) return;
	S=node[l],T=node[l+1];
	int t=maxflow(),ss=node[l],tt=node[l+1];
	ans[S][T]=ans[T][S]=t;
	int ltot=0,rtot=0;
	for(int i=l;i<=r;i++){
		if(dep[node[i]]) tl[++ltot]=node[i];
		else tr[++rtot]=node[i];
	}
	for(int i=1;i<=ltot;i++) node[i+l-1]=tl[i];
	for(int i=1;i<=rtot;i++) node[ltot+l+i-1]=tr[i];
	GomoryHu(l,l+ltot-1);
	GomoryHu(l+ltot,r);
	for(int i=1;i<=ltot;i++){
		for(int j=1;j<=rtot;j++){
			int ii=node[i+l-1],jj=node[j+ltot+l-1];
			ans[ii][jj]=ans[jj][ii]=min(min(ans[ii][ss],ans[ss][tt]),ans[tt][jj]);
		}
	}
}

课后习题

P4897 【模板】最小割树(Gomory-Hu Tree)

给出 \(n+1\) 个点和 \(m\) 条边的 无向图,\(Q\) 组询问,每组询问给出两个点,求两点之间的最小割。

\(1 \leq n \leq 500,1 \leq m \leq 1500,1 \leq Q \leq 10^5\)

P3329 [ZJOI2011]最小割

\(T\) 组数据,每组数据给出 \(n\) 个点和 \(m\) 条边的有向图,\(q\) 组询问,每组询问一个 \(x\),求出有多少对点满足最小割小于等于 \(x\)。在两组测试数据之间需要输出一行空行。

\(1 \leq T \leq 10\),\(1 \leq n \leq 150\),\(0 \leq m \leq 3000\),\(0 \leq x \leq 2^{31}-1\),\(0 \leq q \leq 30\)

P4123 [CQOI2016]不同的最小割

给出 \(N\) 个点 \(M\) 条边的有向图,求任意两点的最小割有多少种。

\(1\leq N\leq 850,1\leq M\leq 8500\)

标签:个点,int,最小,笔记,leq,条边,割树
From: https://www.cnblogs.com/zheyuanxie/p/gomory-hu-tree.html

相关文章

  • 数据结构笔记1 绪论 概念
    最近这一段时间在学习数据结构。感觉还是很值得的。有老大的话说就是这次投资成功了。开始决定学习的时候买了一本书《数据结构(C语言版)》相信大家都看过吧。是严蔚敏老师......
  • 数据结构笔记4 栈
    栈的定义和概念栈(Stack)是限制仅在表的一端进行插入和删除运算的线性表。(1)通常称插入、删除的这一端为栈顶(Top),另一端称为栈底(Bottom)。(2)当表中没有元素......
  • 使用Jieba分词学习PaddleNLP(学习笔记)
    最近疫情肆虐,实现了我在家办公的愿望,也有更多的时间学习了,于是我参加百度深度学习集训营,刚刚接触新领域,以下是我整理的学习笔记,与大家分享:首先是此次的作业帖:​​h......
  • MybatisPlus学习笔记
    MybatisPlus初始化创建boot项目的时候导入mysql的依赖,创建好以后在里边导入MybatisPlus的坐标(这个坐标包含和mybatis的相关坐标和spring整合mybatis的相关坐标,所以自......
  • 性能测试技术笔记(三):如何设计一个压测平台
    转载:https://www.cnblogs.com/imyalost/p/17031603.html前面两篇笔记介绍了如何快速上手压测项目以及压测前准备测试环境和测试数据的一些方法。这篇文章,我想分享下关于......
  • 笔记-应用向量自回归模型脉冲效应函数的注意事项
    计量经济模型Econometricmodels2022-07-2718:51发表于江苏https://mp.weixin.qq.com/s/_ZVeVySe319Ap4UvvmnHWA向量自回归模型,VectorAutoregressionModels,VAR,......
  • 3/21人月神话读书笔记
    作为开章第一篇,就先来说说为什么“人月”是“神话”。小学的时候我们都做过这样的应用题:“工厂需要加工一批零件,安排5名工人的话需要10小时完成,那么安排25名工人加工,多少......
  • Leetcode209. 长度最小的子数组
    题目跳转链接滑动窗口解法代码随想录209.长度最小的子数组滑动窗口是一种基于双指针的算法,它可以用于解决一些数组/字符串的子元素问题,例如:找到最长的子数组、最小的子......
  • Django笔记四之字段属性
    这篇笔记介绍的fieldoptions,也就是字段的选项属性。首先,关于model,是数据库与python代码里的一个映射关系,每一个model是django.db.models.Model的一个子类。mode......
  • jenkins学习笔记之十五:SonarSQube API使用
    本章主要通过SonarSQubeAPI在pipeline第一次执行时就指定自定义的质量配置和质量阈API 文档:http://192.168.1.134:9000/web_api一、编写sonarAPI(sonarapi.groovy)注......