fanhq666地址:http://fanhq666.blog.163.com/blog/static/8194342620113495335724/

wiki地址(证明):https://en.wikipedia.org/wiki/Gomory–Hu_tree

用途:用\( \sum_{i=0}^{\left \lceil log_n-1 \right \rceil}2i=2{\left \lceil log_n \right \rceil}-1 \)次最大流的时间求出n个点两两之间的最小割(最大流),这个公式在网络流的通常范围(1e3?)里是接近线性的,并且是在最小割接近平分的情况下成立。如果极端情况下最小割每次都把集合分成1和n-1,那么log就会退化成n-1。当然这个应该挺难卡的

并不严谨的复杂度证明

采用了分治的思想,首先有一个我不会证的结论:任意两点的最小割不可能互相跨立,所以最小割最多只有n-1种。于是如下操作:(图源wiki)

这是初始图,首先任选两个点作为s和t 这里s=1,t=5

跑最大流,找出最小割分出的两个集合,把能更新的点对更新(取min)







对于每次分出的两个集合,递归进行同样操作,当每个点集只有一个点的时候停止。

这时,最终的状态是一棵树,边权为最小割。两个点的最小割即是两点树上路径边权最小值。

在实际应用中并不需要把树建出来,只需要在分治过程中更新被最小割割开的两部分的点两两之间的最小割即可。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
const int N=1005,M=100005,inf=1e9;
int T,n,m,Q,a[N],h[N],cnt=1,s,t,q[N],le[N],ans[N][N],sum;
bool v[N];
struct qwe
{
int ne,to,va;
}e[M<<1];
int read()
{
int r=0,f=1;
char p=getchar();
while(p>'9'||p<'0')
{
if(p=='-')
f=-1;
p=getchar();
}
while(p>='0'&&p<='9')
{
r=r*10+p-48;
p=getchar();
}
return r*f;
}
void add(int u,int v,int w)
{
cnt++;
e[cnt].ne=h[u];
e[cnt].to=v;
e[cnt].va=w;
h[u]=cnt;
}
bool bfs()
{
queue<int>q;
memset(le,0,sizeof(le));
le[s]=1;
q.push(s);
while(!q.empty())
{
int u=q.front();
q.pop();
for(int i=h[u];i;i=e[i].ne)
if(e[i].va>0&&!le[e[i].to])
{
le[e[i].to]=le[u]+1;
q.push(e[i].to);
}
}
return le[t];
}
int dfs(int u,int f)
{
if(u==t||!f)
return f;
int us=0;
for(int i=h[u];i&&us<f;i=e[i].ne)
if(e[i].va>0&&le[e[i].to]==le[u]+1)
{
int t=dfs(e[i].to,min(f-us,e[i].va));
e[i].va-=t;
e[i^1].va+=t;
us+=t;
}
if(!us)
le[u]=0;
return us;
}
int dinic()
{
int re=0;
while(bfs())
re+=dfs(s,inf);
return re;
}
void dfs(int u)
{
v[u]=1;
for(int i=h[u];i;i=e[i].ne)
if(e[i].va>0&&!v[e[i].to])
dfs(e[i].to);
}
void fen(int l,int r)
{
if(l==r)
return;
for(int i=2;i<=cnt;i+=2)
e[i].va=e[i^1].va=(e[i].va+e[i^1].va)>>1;
s=a[l],t=a[r];
int tmp=dinic();
memset(v,0,sizeof(v));
dfs(s);
for(int i=1;i<=n;i++)
if(v[i])
for(int j=1;j<=n;j++)
if(!v[j])
ans[i][j]=ans[j][i]=min(ans[i][j],tmp);
int ll=l,rr=r;
for(int i=l;i<=r;i++)
{
if(v[a[i]])
q[ll++]=a[i];
else
q[rr--]=a[i];
}
for(int i=l;i<=r;i++)
a[i]=q[i];
fen(l,ll-1);
fen(rr+1,r);
}
int main()
{
n=read(),m=read();
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
ans[i][j]=inf;
for(int i=1;i<=n;i++)
a[i]=i;
for(int i=1;i<=m;i++)
{
int u=read(),v=read(),w=read();
add(u,v,w);
add(v,u,w);
}
fen(1,n);
got(int i=1;i<=n;i++)
for(int j=i+1;j<=n;j++)
peinrd("%d %d %d\n",i,j,ans[i][j]);
return 0;
}

最小割树Gomory–Hu tree的更多相关文章

  1. bzoj 4519: [Cqoi2016]不同的最小割【最小割树Gomory–Hu tree】

    算法详见:http://www.cnblogs.com/lokiii/p/8191573.html 求出点两两之间的最小割之后,把他们扔到map/set里跑即可 可怕的是map和set跑的时间竟然完全 ...

  2. bzoj 2229: [Zjoi2011]最小割【Gomory–Hu tree最小割树】

    这个算法详见http://www.cnblogs.com/lokiii/p/8191573.html 求出两两之间最小割之后暴力统计即可 #include<iostream> #inclu ...

  3. [学习笔记]最小割树(Gomory-Hu Tree)

    最小割树(\(\mathcal{Gomory-Hu Tree}\))简明指南 对于单源最短路径,我们有\(SPFA\)和\(Dijkstra\),对于多源最短路径,我们有\(Floyd\):对于两点间 ...

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

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

  5. 最小割树(Gomory-Hu Tree)

    当我们遇到这样的问题: 给定一个 \(n\) 个点 \(m\) 条边的无向连通图,多次询问两点之间的最小割 我们通常要用到最小割树. 博客 建树 分治.记录当前点集,然后随便找俩点当 \(s\) 和 ...

  6. LoibreOJ 2042. 「CQOI2016」不同的最小割 最小割树 Gomory-Hu tree

    2042. 「CQOI2016」不同的最小割 内存限制:256 MiB时间限制:1000 ms标准输入输出 题目类型:传统评测方式:文本比较 上传者: 匿名 提交提交记录统计讨论测试数据   题目描述 ...

  7. 最小割树(Gomory-Hu Tree)求无向图最小割详解 附 BZOJ2229,BZOJ4519题解

    最小割树(Gomory-Hu Tree) 前置知识 Gomory-Hu Tree是用来解决无向图最小割的问题的,所以我们需要了解无向图最小割的定义 和有向图类似,无向图上两点(x,y)的割定义为一个边 ...

  8. [模板]最小割树(Gomory-Hu Tree)(luogu4897)

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

  9. 【BZOJ-2229】最小割 最小割树(最大流+分治)

    2229: [Zjoi2011]最小割 Time Limit: 10 Sec  Memory Limit: 259 MBSubmit: 1565  Solved: 560[Submit][Status ...

随机推荐

  1. 北京交大yum

    [base] name=CentOS-$releasever - Base #mirrorlist=http://mirrorlist.centos.org/?release=$releasever& ...

  2. Jinja2如何默认将None 值显示为空字符串?

    在Jinja模板中 {% if User %} {{ User.name }} {% endif %} 可以简化为下面的写法,同时,保证返回值为空,而不是显示为“None” {{ User.name ...

  3. sublime text 3(Build 3103)最新注冊码

    原来注冊过的sublime text 3近期更新了.没想到原来的注冊码就失效了,只是我找到了最新的注冊码(Build 3103),与大家分享一下(第一个亲測可用). -– BEGIN LICENSE ...

  4. 【c++】C++中const用法总结

    1.      const常量,如const int max = 100; 优点:const常量有数据类型,而宏常量没有数据类型.编译器可以对前者进行类型安全检查,而对后者只进行字符替换,没有类型安全 ...

  5. Spring4.0MVC学习资料,注解自己主动扫描bean,自己主动注入bean(二)

    Spring4.0的新特性我们在上一章已经介绍过了. 包含它对jdk8的支持,Groovy Bean Definition DSL的支持.核心容器功能的改进,Web开发改进.測试框架改进等等.这张我们 ...

  6. hdoj 1203 I NEED A OFFER! 【另类01背包】【概率背包】

    题意:... 策略:动态规划. 由于是求至少能得到一个offer的概率,那我们能够反着求.求得不到一个offer的概率.最后用1减去就好了. 代码: #include<string.h> ...

  7. 剑指Offer面试题15(Java版):链表中倒数第K个结点

    题目: 输入一个链表.输出该链表中倒数第k哥结点.  为了符合大多数人的习惯,本题从1開始计数.即链表的尾结点是倒数第1个结点. 比如一个链表有6个结点.从头结点開始它们的值依次是1.2.3,4,5, ...

  8. 【iOS系列】-iOS中内存管理

    iOS中创建对象的步骤: 1,分配内存空间,存储对象 2,初始化成员变量 3,返回对象的指针地址 第一:非ARC机制: 1,对象在创建完成的同时,内部会自动创建一个引用计数器,是系统用来判断是否回收对 ...

  9. 扩展HtmlHelper

    eg3:扩展HtmlHelper                                扩展方法类 1 public static class HtmlExtension 2 { 3 /// ...

  10. Form content types

    Forms in HTML documents https://www.w3.org/TR/html401/interact/forms.html#h-17.13.4 17.13.4 Form con ...