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

这个算法可以用来求解一个无向图上任意两点的最小割,具体过程就是每次选择两个点求最小割,然后在一个新图中这两个点连边,然后对于这两个点的连通块分别递归处理,可以发现这样得到的一定是一个树,然后两个点的最小割等于这两个点在树链上的边权最小值,可以倍增求解。

具体证明:
https://www.cnblogs.com/birchtree/p/10761585.html

代码细节:
记得无向图网络流建边要双向连,所以一共需要条边,另外还要注意每一次重新求解要将流量数组还原,这里的最小割依然是整张图上的,不是递归范围的。

#include<bits/stdc++.h>
#define LL long long
#define V inline void
#define I inline int
#define FOR(i,a,b) for(register int i=a,end##i=b;i<=end##i;++i)
#define REP(i,a,b) for(register int i=a,end##i=b;i>=end##i;--i)
using namespace std;
inline int read()
{char x='\0';int fh=1,sum=0;for(x=getchar();x<'0'||x>'9';x=getchar())if(x=='-')fh=-1;for(;x>='0'&&x<='9';x=getchar())sum=sum*10+x-'0';return fh*sum;
}
const int N=2009,M=4009,INF=0x3f3f3f3f;
int n,m,q;
namespace netflow{struct lian{int to,pre,cap;}e[M<<1];int hed[N],lcnt=1;V jlian(int x,int y,int cap){e[++lcnt]={y,hed[x],cap};hed[x]=lcnt;e[++lcnt]={x,hed[y],0};hed[y]=lcnt;}int cur[N],dep[N];queue<int>q;I bfs(int S,int T){memcpy(cur,hed,sizeof(hed));memset(dep,0,sizeof(dep));dep[S]=1,q.push(S);while(!q.empty()){int now=q.front();q.pop();for(int i=hed[now];i;i=e[i].pre){int to=e[i].to;if(e[i].cap&&dep[to]==0){dep[to]=dep[now]+1;q.push(to);}}}return dep[T]!=0;}I dfs(int now,int T,int flow){if(now==T||flow==0)return flow;int res=flow;for(int &i=cur[now];i;i=e[i].pre){int to=e[i].to;if(e[i].cap&&dep[now]+1==dep[to]){int k=dfs(to,T,min(res,e[i].cap));e[i].cap-=k,e[i^1].cap+=k,res-=k;if(res==0)break;}}return flow-res;}V init(){for(int i=2;i<=lcnt;i+=2){e[i].cap+=e[i^1].cap;e[i^1].cap=0;}}I dinic(int S,int T){init();int maxflow=0;while(bfs(S,T))maxflow+=dfs(S,T,INF);return maxflow;}
}namespace mincut{struct lian{int to,pre,w;}e[N<<1];int hed[N],lcnt=1;inline void jlian(int x,int y,int w){e[++lcnt]={y,hed[x],w};hed[x]=lcnt;}int node[N],tmp1[N],tmp2[N];V build(int lp,int rp){if(lp==rp)return;int s=node[lp],t=node[lp+1];
//      cout<<"s t "<<s<<' '<<t<<endl;int ct=netflow::dinic(s,t);
//      cout<<"cut "<<ct<<endl;//jlian(s,t,ct),jlian(t,s,ct);int cnt1=0,cnt2=0;FOR(i,lp,rp){if(netflow::dep[node[i]])tmp1[++cnt1]=node[i];else tmp2[++cnt2]=node[i];}int cnt=lp;FOR(i,1,cnt1)node[cnt++]=tmp1[i];FOR(i,1,cnt2)node[cnt++]=tmp2[i];build(lp,lp+cnt1-1);build(lp+cnt1,rp);}int dep[N],bz[N][11],mn[N][11];V dfs(int x,int fa,int depth){dep[x]=depth,bz[x][0]=fa;for(int i=1;i<=10;i++){bz[x][i]=bz[bz[x][i-1]][i-1];mn[x][i]=min(mn[x][i-1],mn[bz[x][i-1]][i-1]);}for(int i=hed[x];i;i=e[i].pre){int to=e[i].to;if(to==fa)continue;mn[to][0]=e[i].w;dfs(to,x,depth+1);}}V solve(){memset(mn,0x3f,sizeof(mn));FOR(i,1,n)node[i]=i;build(1,n);dfs(1,0,1);}I que(int x,int y){int ans=0x3f3f3f3f;if(dep[x]<dep[y])swap(x,y);REP(i,10,0){if(dep[bz[x][i]]>=dep[y])ans=min(ans,mn[x][i]),x=bz[x][i];}if(x==y)return ans;REP(i,10,0){if(bz[x][i]!=bz[y][i]){ans=min(ans,mn[x][i]);ans=min(ans,mn[y][i]);x=bz[x][i],y=bz[y][i];}}ans=min(ans,mn[x][0]);ans=min(ans,mn[y][0]);return ans;}
}int main()
{//  freopen("P4897_1.in","r",stdin);n=read()+1,m=read();
//  cout<<n<<' '<<m<<endl;//FOR(i,1,m){int x=read()+1,y=read()+1,cap=read();netflow::jlian(x,y,cap);netflow::jlian(y,x,cap);}
//  cout<<"flow "<<netflow::dinic(2,3)<<endl;mincut::solve();q=read();FOR(i,1,q){int u=read()+1,v=read()+1;printf("%d\n",mincut::que(u,v));}return 0;
}

P4897 【模板】最小割树(Gomory-Hu Tree)(网络流/最小割/树形结构)相关推荐

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

    传送门 Description 给定一个\(n\)个点\(m\)条边的无向连通图,多次询问两点之间的最小割 两点间的最小割是这样定义的:原图的每条边有一个割断它的代价,你需要用最小的代价使得这两个点不 ...

  2. php list 转tree,PHP 数组转树形结构

    之前写过同样功能的,使用的递归,代码丑陋不堪,偶然发现写的非常好的实现,摘抄如下: 直接上代码 /** * 把返回的数据集转换成Tree * @param array $list 要转换的数据集 * ...

  3. C++kruskals算法生成最小协议树(附完整源码)

    C++kruskals算法生成最小协议树 C++kruskals算法生成最小协议树完整源码(定义,实现,main函数测试) C++kruskals算法生成最小协议树完整源码(定义,实现,main函数测 ...

  4. 总结下各种常见树形结构的定义及特点(二叉树、AVL树、红黑树、Trie树、B树、B+树)

    文章目录 前言 一棵普通的树 相关术语 二叉树 二叉树性质 二叉树特例 二叉查找树 AVL树 特点及应用 红黑树 特点 应用 Trie树 特点及应用 B树 定义及特点 应用 B+树 B+树的优势及应用 ...

  5. 树形结构 —— 树与二叉树

    [概述] 树是一种非线性的.递归定义的有序数据结构,能很好地描述有分支和层次特性的数据集合. 二叉树是树的一种形态,是 n 个结点的有限集合,该集合或为空集(空二叉树),或由一个根结点与两棵互不相交的 ...

  6. 洛谷.4897.[模板]最小割树(Dinic)

    题目链接 最小割树模板.具体见:https://www.cnblogs.com/SovietPower/p/9734013.html. ISAP不知为啥T成0分了.. Dinic: //1566ms ...

  7. P3329-[ZJOI2011]最小割【最小割树】

    正题 题目链接:https://www.luogu.com.cn/problem/P3329 题目大意 nnn个点mmm条边的无向图,每次询问一个xxx表示最小割不超过xxx的点对数量. 解题思路 我 ...

  8. bzoj2229: [Zjoi2011]最小割(最小割树)

    传送门 这题是用最小割树做的(不明白最小割树是什么的可以去看看这一题->这里) 有了最小割树就很简单了--点数那么少--每次跑出一个最大流就暴力搞一遍就好了 1 //minamoto 2 #in ...

  9. JZOJ 5495 MiniumCut (最小割树)

    MiniumCut Description 从前有张图. 图里 n 个顶点两两之间有 n2n2n^2 种最小割. 告诉你这 n2n2n^2 个最小割. 还原出这张图. Input 第一行一个正整数 n ...

最新文章

  1. J2EE从servlet开始
  2. python进程池调用实例方法_Python 多进程并发操作中进程池Pool的实例
  3. c++中的pod类型
  4. windows10使用多套public key pair进行SSH连接github的配置文件
  5. LINUX下SYN***战
  6. 【OpenCV】OpenCV函数精讲之 -- 访问图像中的像素--计时函数
  7. Ubuntu下使用UFW配置防火墙(简化iptables的操作)
  8. 多终端同时登录_So easy!同时登陆两个或多个Mac版微信和QQ
  9. JAVA利用google的zxing解析二维码QRCODE
  10. Python办公自动化(三)|批量合并PDF
  11. teamviewer开通防火墙策略
  12. 使用注册表文件(REG)添加、修改或删除windows注册表项和值
  13. 工具_Typora免费版下载(Typora最后一个免费版)md编辑器
  14. 修改DNS服务器的作用,请问修改DNS服务器会有什么后果
  15. 拼多多免单券怎么领取 拼多多免单券是真的吗
  16. 怎么把两段录音合并在一起?
  17. c语言计算年龄的编程,C语言编程实现---计算实际年龄
  18. 【预测模型】基于Logistic混沌映射改进麻雀算法改进BP神经网络实现数据预测matlab源码
  19. 批量删微博丨2023简易版本控制台批量删除微博代码
  20. 颜色传感器 TCS230

热门文章

  1. jdk源码分析书籍 pdf_什么?Spring5 AOP 默认使用Cglib?从现象到源码深度分析
  2. 吃屎是一种什么样的体验?
  3. 千万别让爸妈帮你P图......
  4. 因为没钱买衣服,我女朋友不要我了......
  5. 甜蜜助攻!情侣之间,到底能有多甜甜甜甜甜甜甜甜
  6. 一滴水从高处落下来,会不会砸死人?
  7. 学过物理的人才能看懂的笑话,你能看明白几个?
  8. 一个人开始废掉的3种迹象
  9. detectron2训练自己的数据集_keras版MaskRCNN来训练自己的目标检测数据集
  10. 下图为双总线结构机器的数据通路_海康机器人为物流加码:进击吧,双11新“打工人”...