HDU5511 : Minimum Cut-Cut
设$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的更多相关文章
- linux sort,uniq,cut,wc.
文章转自 http://www.cnblogs.com/ggjucheng/archive/2013/01/13/2858385.html sort sort 命令对 File 参数指定的文件中的行排 ...
- [转]linux sort,uniq,cut,wc命令详解
sort sort 命令对 File 参数指定的文件中的行排序,并将结果写到标准输出.如果 File 参数指定多个文件,那么 sort 命令将这些文件连接起来,并当作一个文件进行排序. sort语法 ...
- linux sort,uniq,cut,wc命令详解
linux sort,uniq,cut,wc命令详解 sort sort 命令对 File 参数指定的文件中的行排序,并将结果写到标准输出.如果 File 参数指定多个文件,那么 sort 命令将这些 ...
- linux sort,uniq,cut,wc,tr命令详解
sort是在Linux里非常常用的一个命令,对指定文件进行排序.去除重复的行 sort 命令对 File 参数指定的文件中的行排序,并将结果写到标准输出.如果 File 参数指定多个文件,那么 sor ...
- Linux之 sort,uniq,cut,wc命令详解
sort sort 命令对 File 参数指定的文件中的行排序,并将结果写到标准输出.如果 File 参数指定多个文件,那么 sort 命令将这些文件连接起来,并当作一个文件进行排序. sort语法 ...
- Linux Shell脚本入门--cut命令
Linux Shell脚本入门--cut命令 cut cut 命令可以从一个文本文件或者文本流中提取文本列. cut语法 [root@www ~]# cut -d'分隔字符' -f fields &l ...
- Ubuntu 14.10 下sort,uniq,cut,wc命令详解
sort sort 命令对 File 参数指定的文件中的行排序,并将结果写到标准输出.如果 File 参数指定多个文件,那么 sort 命令将这些文件连接起来,并当作一个文件进行排序. sort语法 ...
- 文本处理命令--cut、sort、join
声明:下面介绍的只是命令的常用选项,如果需要详细了解命令全部细节,需要参考其他的资料. 一.cut cut是一个选取命令,就是将一段数据经过分析,取出我们想要的.一般来说,选取信息通常是针对“行”来进 ...
- Linux Shell脚本编程--cut命令
cut cut命令可以从一个文本文件或者文本流中提取文本列. cut语法 [root@www ~]# cut -d'分隔字符' -f fields <==用于有特定分隔字符 [root@www ...
随机推荐
- .NET C# 创建WebService服务简单的例子
Web service是一个基于可编程的web的应用程序,用于开发分布式的互操作的应用程序,也是一种web服务 WebService的特性有以下几点: 1.使用XML(标准通用标记语言)来作为数据交互 ...
- 分库分表之后全局id怎么生成
数据库自增id: 这个就是说你的系统里每次得到一个id,都是往一个库的一个表里插入一条没什么业务含义的数据,然后获取一个数据库自增的一个id.拿到这个id之后再往对应的分库分表里去写入. 这个方案的好 ...
- file /usr/share/mysql/charsets/README from install of MySQL-server-5.1.73-1.glibc23.i386 conflicts with file from package mysql-libs-5.1.73-8.el6_8.i686
1:也许之前的机器安装过Mysql,但是自己不知道,账号密码也忘记了,又执行安装操作,导致Mysql不兼容问题.Linux上安装MySQL时出现不兼容的解决办法,错误如下所示: [root@maste ...
- Linux系统监控命令及定位Java线程
1.PID.TID的区分 uid是user id,即用户id,root用户的uid是0,0为最高权限,gid是group id,用户组id,使用 id 命令可以很简单的通过用户名查看UID.GID:~ ...
- DataFrames和Kudu
Kudu为Kudu表提供了一个自定义的原生数据源.可以和DataFrame API紧密集成: 使用DataFrame的好处就是可以从很多的数据源创建dataframe,包括现有的RDD,Hive表或S ...
- Python学习(三) —— 基本数据类型
基本数据类型 一.整数类型(int) 32位机器,整数的位数为32位,取值范围为-2**31~2**31-1,即-2147483648~2147483647 64位机器,整数的位数是64位,取值范围位 ...
- BZOJ2821 作诗(Poetize) 主席树 bitset
原文链接https://www.lydsy.com/JudgeOnline/problem.php?id=2821 题目传送门 - BZOJ2821 题意 $n$ 个数,$m$ 组询问,每次问 $[l ...
- 防止vs编译时自动启动单元测试
Tools → Options → Live Unit Testing Pause 勾选
- tesorflow - create neural network+结果可视化+加速神经网络训练+Optimizer+TensorFlow
以下仅为了自己方便查看,绝大部分参考来源:莫烦Python,建议去看原博客 一.添加层 def add_layer() 定义 add_layer()函数 在 Tensorflow 里定义一个添加层的函 ...
- day 68 django 之api操作 | jQueryset集合与对象
我们的orm里面分为: jQueryset集合, 还有对象, 我们的jqueryset集合里面可以有多个对象,这句话的意思就是我们的对象是最小的单位,不可以再拆分了,我们的jQueryset集合就相当 ...