传送门

Description

给定一个\(n\)个点\(m\)条边的无向连通图,多次询问两点之间的最小割

两点间的最小割是这样定义的:原图的每条边有一个割断它的代价,你需要用最小的代价使得这两个点不连通

Solution

对于一张无向图,如果 \(s \rightarrow t\) 的最大流是 \(f\),\(s\), \(t\) 所在的割集为 \(S\), \(T\),那么 \(\forall_{x \in S, y \in T}\), \(\operatorname{maxflow}(x \rightarrow y) = f\)

根据以上性质,我们考虑递归求解

构造集合 \(G\) 的最小割树:

  • 任意选两个点,求出最小割,在两个点之间连权值为最小割的边
  • 对两个割集分别求解

\(Wa\)了数十次

以后用static的时候还是注意点

Code 

#include<bits/stdc++.h>
#define ll long long
#define reg register
#define ri reg int i
using namespace std; inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
return x*f;
} const int MN=505,MM=1505,inf=1e9; struct edge{int to,w,nex;}e[MM<<1],E[MN<<1];int cur[MN],Hr[MN],hr[MN],En=1,en=1;
void ins(int x,int y,int w,int *h,edge *ed,int &tt)
{
ed[++tt]=(edge){y,w,h[x]},h[x]=tt;
ed[++tt]=(edge){x,w,h[y]},h[y]=tt;
} int d[MN],q[MN],top; bool bfs(int S,int T)
{
memset(d,0,sizeof d);
reg int i,j;
for(d[q[i=top=1]=S]=1;i<=top;++i)
for(j=hr[q[i]];j;j=e[j].nex)
if(e[j].w&&!d[e[j].to])
d[q[++top]=e[j].to]=d[q[i]]+1;
return d[T];
} int dfs(int x,int T,int f)
{
if(x==T) return f;
int used=0;
for(int &i=cur[x];i;i=e[i].nex)
if(e[i].w&&d[e[i].to]==d[x]+1)
{
int tmp=dfs(e[i].to,T,min(f-used,e[i].w));
e[i].w-=tmp,e[i^1].w+=tmp;used+=tmp;
if(f==used) return f;
}
return d[x]=-1,used;
} void clear(){for(reg int i=2;i<en;i+=2)e[i].w=e[i^1].w=(e[i].w+e[i^1].w)>>1;} int dinic(int S,int T)
{
int maxflow=0;clear();
while(bfs(S,T))
{
memcpy(cur,hr,sizeof cur);
maxflow+=dfs(S,T,inf);
}
return maxflow;
} void Build(int *id, int n)
{
if(n==1) return;
static int s[MN],t[MN];int cnts=0,cntt=0;
int cut=dinic(id[0],id[1]);
ins(id[0],id[1],cut,Hr,E,En);
for(reg int i=0;i<n;++i)
if(d[id[i]]) s[cnts++]=id[i];
else t[cntt++]=id[i];
memcpy(id,s,cnts<<2);
memcpy(id+cnts,t,cntt<<2);
if(cnts) Build(id,cnts);
if(cntt) Build(id+cnts,cntt);
} int n,dep[MN],fa[MN][15],path[MN][15]; void init_dfs(int x,int f)
{
for(ri=Hr[x];i;i=E[i].nex)if(E[i].to!=f)
dep[E[i].to]=dep[x]+1,fa[E[i].to][0]=x,path[E[i].to][0]=E[i].w,init_dfs(E[i].to,x);
} void init()
{
dep[1]=1;init_dfs(1,-1);reg int i,j;
for(i=1;i<10;++i)for(j=1;j<=n;++j)
{
fa[j][i]=fa[fa[j][i-1]][i-1];
path[j][i]=min(path[j][i-1],path[fa[j][i-1]][i-1]); }
} int Min(int x,int y)
{
reg int ret=1e9;
if(dep[x]>dep[y]) std::swap(x,y);
reg int i,c=dep[y]-dep[x];
for(i=8;~i;--i) if(c>>i&1)
{
ret=min(ret,path[y][i]),y=fa[y][i];
}
if(x==y) return ret;
if(dep[x]!=dep[y]) return -1;
for(i=8;~i;--i)if(fa[x][i]!=fa[y][i])
{
ret=min(ret,min(path[x][i],path[y][i])),x=fa[x][i],y=fa[y][i];
}
return min(ret,min(path[x][0],path[y][0]));
} int id[MN];
int main()
{
reg int i,m,q,x,y;
n=read(),m=read();
while(m--) x=read(),y=read(),ins(x,y,read(),hr,e,en); for(i=1;i<=n;++i) id[i-1]=i;Build(id,n);init(); q=read(); while(q--)
{
x=read();y=read();
printf("%d\n",Min(x,y));
}
return 0;
}

Blog来自PaperCloud,未经允许,请勿转载,TKS!

【模板】最小割树(Gomory-Hu Tree)的更多相关文章

  1. 最小割树Gomory–Hu tree

    fanhq666地址:http://fanhq666.blog.163.com/blog/static/8194342620113495335724/ wiki地址(证明):https://en.wi ...

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

随机推荐

  1. MSMQ消息加密

    证书实现非对称加密/解密的代码如下 //非对称加密密钥 static byte[] RSAEncrypt(byte[] enkey, X509Certificate2 Certificate) { R ...

  2. GIt三剑客

    一. Github 什么是Github? github是一个基于git的代码托管平台,付费用户可以建私人仓库,我们一般的免费用户只能使用公共仓库,也就是代码要公开. Github 由Chris Wan ...

  3. vue 全局挂载组件

    <!-- plugin.js --> import someComponent from './components/someComponent' export default { ins ...

  4. tkinter 按钮响应函数传值

    tkinter 中的Button组件的响应函数如何传入参数,可能非常困扰新手,这里记录一下. 步骤: 1. 写好响应函数(形参设置好) 2. 在Button command 设置形式:command ...

  5. python实战项目

    没有一个完整的项目开发过程,是不会对整个开发流程以及理论知识有牢固的认知的,对于怎样将所学的理论知识应用到实际开发中更是不得而知了! 以上就是我们在学习过程中必须要有项目实战开发经验的原因,其实无论项 ...

  6. Mysql中decode函数的几种用法

    1.使用decode判断字符串是否一样 decode(value,if1,then1,if2,then2,if3,then3,...,else) 含义为 IF 条件=值1 THEN RETURN(va ...

  7. mybatis中如何将多个表的查询结果,放入结果集中返回

    1.首先需要将resultMap进行改造,为了避免对其他sql的影响建议另外定义一个resultMapExtral,避免id相同, 2.然后在resultMapExtral中添加其它表的字段,若多个表 ...

  8. 个人第5次作业:Alpha2项目的测试

    这个作业属于哪个课程 <课程的链接> 这个作业要求在哪里 <作业要求的链接> 名字 易林 学号 201731062134 团队名称 <巧克力王子和六个小矮人> 第一 ...

  9. Python for Email

    SMTP 正如 HTTP 是计算机用来通过因特网发送网页的协议,简单邮件传输协议(SMTP) 是用于发送电子邮件的协议 import smtplib 发送电子邮件 连接到SMTP服务器 smtpObj ...

  10. 《你说对就队》第九次团队作业:Beta冲刺与验收准备

    <你说对就队>第九次团队作业:Beta冲刺与验收准备 项目 内容 这个作业属于哪个课程 [教师博客主页链接] 这个作业的要求在哪里 [作业链接地址] 团队名称 <你说对就队> ...