设$d[x]$表示端点位于$x$子树内部的非树边条数,那么有两种情况:

$1.$割去的两条树边$(x,fa[x]),(y,fa[y])$中,$x$是$y$的祖先,那么此时需要割去的非树边数量为$d[x]-d[y]$。

显然固定$x$之后$y$越靠上越好,因此$y$一定是$x$的儿子,枚举即可,时间复杂度$O(n)$。

$2.$一般化的情况,此时$x\neq y$,需要割去的非树边数量为$d[x]+d[y]-2cnt(x,y)$,其中$cnt(x,y)$表示一端在$x$子树中,另一端在$y$子树中的非树边数量。

枚举$x$,对于每个$y$维护$d[y]-2cnt(x,y)$。

首先需要把$x$子树的$cnt$合并,然后对于一条端点恰好为$x$的非树边$(x,u)$,需要把$u$到根路径上的$d-2cnt$都减去$2$。

树链剖分+线段树维护即可,时间复杂度$O(m\log^2n)$。

直接实现的话,空间复杂度也为$O(m\log^2n)$,不能承受。

每次先dfs重儿子,将$x$的重儿子的线段树直接作为$x$的线段树,然后依次与轻儿子合并,同时将废弃线段树节点回收利用。

如此一来,只有经过轻边时,才会多开一棵动态开点的线段树,那么一共只会同时存在$O(\log n)$棵线段树。

每棵线段树就算开满也只有$O(n)$的空间,因此空间复杂度为$O(n\log n)$。

#include<cstdio>
const int N=20010,M=100010,E=1200000;
int Case,cas,n,m,i,x,y,g[N],v[N<<1],nxt[N<<1],ed,ans;
int d[N],G[N],V[M<<1],NXT[M<<1],ED;
int f[N],size[N],son[N],top[N],loc[N],dfn,q[N];
int T[N],l[E],r[E],tag[E],val[E],pool[E],cur,w[66000];
inline void add(int x,int y){v[++ed]=y;nxt[ed]=g[x];g[x]=ed;}
inline void ADD(int x,int y){d[x]++;V[++ED]=y;NXT[ED]=G[x];G[x]=ED;}
inline void umin(int&a,int b){a>b?(a=b):0;}
inline int min(int a,int b){return a<b?a:b;}
void dfs(int x){
size[x]=1;
for(int i=g[x];i;i=nxt[i])if(v[i]!=f[x]){
f[v[i]]=x;
dfs(v[i]);
size[x]+=size[v[i]],d[x]+=d[v[i]];
if(size[v[i]]>size[son[x]])son[x]=v[i];
}
if(x>1)for(int i=g[x];i;i=nxt[i])if(v[i]!=f[x])umin(ans,d[x]-d[v[i]]);
}
void dfs2(int x,int y){
loc[x]=++dfn;top[x]=y;
if(son[x])dfs2(son[x],y);
for(int i=g[x];i;i=nxt[i])if(v[i]!=son[x]&&v[i]!=f[x])dfs2(v[i],v[i]);
}
void build(int x,int a,int b){
if(a==b){w[x]=q[a];return;}
int mid=(a+b)>>1;
build(x<<1,a,mid),build(x<<1|1,mid+1,b);
w[x]=min(w[x<<1],w[x<<1|1]);
}
inline int newnode(int o){
int x=pool[cur--];
l[x]=r[x]=tag[x]=0;val[x]=w[o];
return x;
}
inline void tag1(int x,int p){tag[x]+=p;val[x]+=p;}
inline void pb(int x,int o){
if(tag[x]){
if(!l[x])l[x]=newnode(o<<1);
if(!r[x])r[x]=newnode(o<<1|1);
tag1(l[x],tag[x]),tag1(r[x],tag[x]),tag[x]=0;
}
}
inline void up(int x,int o){
if(!l[x])l[x]=newnode(o<<1);
if(!r[x])r[x]=newnode(o<<1|1);
val[x]=min(val[l[x]],val[r[x]]);
}
void change(int&x,int o,int a,int b,int c,int d,int p){
if(!x)x=newnode(o);
if(c<=a&&b<=d){tag1(x,p);return;}
pb(x,o);
int mid=(a+b)>>1;
if(c<=mid)change(l[x],o<<1,a,mid,c,d,p);
if(d>mid)change(r[x],o<<1|1,mid+1,b,c,d,p);
up(x,o);
}
inline void chain(int&T,int x){
while(top[x]!=1)change(T,1,1,n,loc[top[x]],loc[x],-2),x=f[top[x]];
if(x>1)change(T,1,1,n,2,loc[x],-2);
}
int merge(int x,int y,int o,int a,int b){
if(!x||!y)return x+y;
if(a==b)tag[x]+=tag[y];
else{
pb(x,o),pb(y,o);
int mid=(a+b)>>1;
l[x]=merge(l[x],l[y],o<<1,a,mid);
r[x]=merge(r[x],r[y],o<<1|1,mid+1,b);
up(x,o);
}
pool[++cur]=y;
return x;
}
void clear(int x,int a,int b){
if(!x)return;
pool[++cur]=x;
if(a==b)return;
int mid=(a+b)>>1;
clear(l[x],a,mid),clear(r[x],mid+1,b);
}
void dfs3(int x){
if(son[x])dfs3(son[x]),T[x]=T[son[x]];
for(int i=g[x];i;i=nxt[i])if(v[i]!=son[x]&&v[i]!=f[x])dfs3(v[i]),T[x]=merge(T[x],T[v[i]],1,1,n);
if(x==1)return;
for(int i=G[x];i;i=NXT[i])chain(T[x],V[i]);
change(T[x],1,1,n,loc[x],loc[x],M);
umin(ans,d[x]+val[T[x]]);
change(T[x],1,1,n,loc[x],loc[x],-M);
}
int main(){
for(i=1;i<E;i++)pool[++cur]=i;
scanf("%d",&Case);
for(cas=1;cas<=Case;cas++){
scanf("%d%d",&n,&m);ans=M;
for(i=1;i<n;i++)scanf("%d%d",&x,&y),add(x,y),add(y,x);
for(;i<=m;i++)scanf("%d%d",&x,&y),ADD(x,y),ADD(y,x);
dfs(1),dfs2(1,1);
for(i=1;i<=n;i++)q[loc[i]]=d[i];
build(1,1,n);
dfs3(1);
printf("Case #%d: %d\n",cas,ans+2);
clear(T[1],1,n);
for(ed=ED=dfn=0,i=1;i<=n;i++)g[i]=d[i]=G[i]=f[i]=size[i]=son[i]=T[i]=0;
}
return 0;
}

  

HDU5511 : Minimum Cut-Cut的更多相关文章

  1. linux sort,uniq,cut,wc.

    文章转自 http://www.cnblogs.com/ggjucheng/archive/2013/01/13/2858385.html sort sort 命令对 File 参数指定的文件中的行排 ...

  2. [转]linux sort,uniq,cut,wc命令详解

    sort sort 命令对 File 参数指定的文件中的行排序,并将结果写到标准输出.如果 File 参数指定多个文件,那么 sort 命令将这些文件连接起来,并当作一个文件进行排序. sort语法 ...

  3. linux sort,uniq,cut,wc命令详解

    linux sort,uniq,cut,wc命令详解 sort sort 命令对 File 参数指定的文件中的行排序,并将结果写到标准输出.如果 File 参数指定多个文件,那么 sort 命令将这些 ...

  4. linux sort,uniq,cut,wc,tr命令详解

    sort是在Linux里非常常用的一个命令,对指定文件进行排序.去除重复的行 sort 命令对 File 参数指定的文件中的行排序,并将结果写到标准输出.如果 File 参数指定多个文件,那么 sor ...

  5. Linux之 sort,uniq,cut,wc命令详解

    sort sort 命令对 File 参数指定的文件中的行排序,并将结果写到标准输出.如果 File 参数指定多个文件,那么 sort 命令将这些文件连接起来,并当作一个文件进行排序. sort语法 ...

  6. Linux Shell脚本入门--cut命令

    Linux Shell脚本入门--cut命令 cut cut 命令可以从一个文本文件或者文本流中提取文本列. cut语法 [root@www ~]# cut -d'分隔字符' -f fields &l ...

  7. Ubuntu 14.10 下sort,uniq,cut,wc命令详解

    sort sort 命令对 File 参数指定的文件中的行排序,并将结果写到标准输出.如果 File 参数指定多个文件,那么 sort 命令将这些文件连接起来,并当作一个文件进行排序. sort语法 ...

  8. 文本处理命令--cut、sort、join

    声明:下面介绍的只是命令的常用选项,如果需要详细了解命令全部细节,需要参考其他的资料. 一.cut cut是一个选取命令,就是将一段数据经过分析,取出我们想要的.一般来说,选取信息通常是针对“行”来进 ...

  9. Linux Shell脚本编程--cut命令

    cut cut命令可以从一个文本文件或者文本流中提取文本列. cut语法 [root@www ~]# cut -d'分隔字符' -f fields <==用于有特定分隔字符 [root@www ...

随机推荐

  1. ajax beforeSend 写的显示隐藏代码不执行

    ajax如果要写像下方格式 $.ajax({ url: ajaxurl, type: 'POST', dataType: 'json', async:true, data: { }, beforeSe ...

  2. 论文阅读笔记十二:Encoder-Decoder with Atrous Separable Convolution for Semantic Image Segmentation(DeepLabv3+)(CVPR2018)

    论文链接:https://arxiv.org/abs/1802.02611 tensorflow 官方实现: https: //github.com/tensorflow/models/tree/ma ...

  3. EF Fluent API

    EntityTypeConfiguration 它可以为一个实体类,配置一个模型. Entity Framework 6 一次加载许多个 Fluent API 映射 如果对于许多实体有大量映射,则 O ...

  4. 微信小程序API 登录-wx.login(OBJECT) + 获取微信用户唯一标识openid | 小程序

    wx.login(OBJECT) 调用接口获取登录凭证(code)进而换取用户登录态信息,包括用户的唯一标识(openid) 及本次登录的 会话密钥(session_key).用户数据的加解密通讯需要 ...

  5. 初学python 遇到的坑

    这最近人工智能比较火,看了一下大多都是python的代码,最近看看python 的代码,一出来就遇到了坑,空格的问题先不说了直接上代码吧 # coding = utf-8 import urllib. ...

  6. some advice in work

    给研究生的建议 文档抄袭自:北航大佬 Fei-Fei Li:De-Mystifying Good Research and Good Papers (repost) 如何提升你的能力?给年轻程序员的几 ...

  7. 【bzoj2131】免费的馅饼 dp+树状数组

    题解: 昨天好像做了个几乎一模一样的题目 按照ti排序 |p[i]-p[j]|<=2*(t[i]-t[j]) 然后去绝对值变为三维偏序 发现后两个式子可以推出ti<tj 所以就变成二维偏序 ...

  8. 【原创】c# socket 粘包 其实。。。

    文章内容有错,请直接关闭~~~不要看了.丢人. private static Dictionary<string, Packet> cache = new Dictionary<st ...

  9. SqlSever大数据分页【转】

       在sql sever中大数据的分页一直是难以处理的一块,利用id自增列分页也存在不足之处.从一个相对全面的分页看,sql sever2005中新增的row_number()函数解决了这个问题.还 ...

  10. Flink应用开发-maven导入

    flink和spark类似,也是一种一站式处理的框架:既可以进行批处理(DataSet),也可以进行实时处理(DataStream) 使用maven导入相关依赖 <properties> ...