【[AHOI2005]航线规划】
树剖维护边双
首先我们看到在整个过程中图是保证连通的,于是我们并不需要LCT来维护连通性
而这些询问询问的是两个点之间关键路径的数量,也就是无论怎么走都必须走的数量,显然这就是两点之间的割边的数量
由于这里还有一些删除操作,树剖并不支持,所以我们先将所有的答案读进来,删掉所有的边
之后我们就\(Tarjan\)把边双缩出来,之后建一棵树就好了
之后我们倒着完成所有操作
对于询问操作,我们直接询问两点之间的距离就行了
对于删除操作,由于我们提前删除完了,所以我们现在需要把边恢复过来,于是我们如果要恢复\((u,v)\)这条边的话,如果\((u,v)\)在一个边双里,我们们不需要管这个操作,而如果不在那么树上\((u,v)\)两点对应边双之间就不会存在桥了,我们直接用树剖将这些边权搞成0就好了
超级长的代码
#include<iostream>
#include<cstring>
#include<cstdio>
#include<set>
#define re register
#define maxn 30005
struct node
{
int v,nxt;
}e[maxn<<3];
int head[maxn],to[maxn],top[maxn],fa[maxn],deep[maxn],sum[maxn],son[maxn];
int a[maxn],b[maxn],belong[maxn];
int opt[maxn<<1],xx[maxn<<1],yy[maxn<<1];
int l[maxn<<2],r[maxn<<2],d[maxn<<2],tag[2][maxn<<2],t[maxn<<2];
int n,m,k,Q,p,num=0;
int tot,now;
inline int read()
{
char c=getchar();
int x=0,r=1;
while(c<'0'||c>'9'){if(c=='-') r=-1;c=getchar();}
while(c>='0'&&c<='9')
x=(x<<3)+(x<<1)+c-48,c=getchar();
return x*r;
}
inline void add_edge(int x,int y)
{
e[++num].v=y;
e[num].nxt=head[x];
head[x]=num;
}
void dfs1(int r)
{
sum[r]=1;
int maxx=-1;
for(re int i=head[r];i;i=e[i].nxt)
if(!deep[e[i].v])
{
deep[e[i].v]=deep[r]+1;
fa[e[i].v]=r;
dfs1(e[i].v);
sum[r]+=sum[e[i].v];
if(sum[e[i].v]>maxx) maxx=sum[e[i].v],son[r]=e[i].v;
}
}
void dfs2(int r,int topf)
{
top[r]=topf;
to[r]=++k;
b[k]=r;
if(!son[r]) return;
dfs2(son[r],topf);
for(re int i=head[r];i;i=e[i].nxt)
if(deep[e[i].v]>deep[r]&&son[r]!=e[i].v) dfs2(e[i].v,e[i].v);
}
void build(int x,int y,int i)
{
l[i]=x;
r[i]=y;
tag[0][i]=tag[1][i]=-1;
if(x==y)
{
t[i]=b[x];
d[i]=1;
return;
}
int mid=x+y>>1;
build(x,mid,i<<1);
build(mid+1,y,i<<1|1);
d[i]=d[i<<1]+d[i<<1|1];
}
inline void pushdown(int i)
{
if(tag[0][i]!=-1&&tag[1][i]!=-1)
{
tag[0][i<<1]=0;
tag[0][i<<1|1]=0;
d[i<<1]=0;
d[i<<1|1]=0;
t[i<<1]=tag[1][i<<1]=tag[1][i];
t[i<<1|1]=tag[1][i<<1|1]=tag[1][i];
tag[0][i]=-1;
tag[1][i]=-1;
}
}
void change(int x,int y,int v1,int v2,int i)
{
if(x<=l[i]&&y>=r[i])
{
d[i]=v1;
t[i]=v2;
tag[0][i]=v1;
tag[1][i]=v2;
return;
}
pushdown(i);
int mid=l[i]+r[i]>>1;
if(y<=mid) change(x,y,v1,v2,i<<1);
else if(x>mid) change(x,y,v1,v2,i<<1|1);
else change(x,y,v1,v2,i<<1),change(x,y,v1,v2,i<<1|1);
d[i]=d[i<<1]+d[i<<1|1];
}
int query(int x,int y,int i)
{
if(x<=l[i]&&y>=r[i]) return d[i];
pushdown(i);
int mid=l[i]+r[i]>>1;
if(y<=mid) return query(x,y,i<<1);
if(x>mid) return query(x,y,i<<1|1);
return query(x,y,i<<1|1)+query(x,y,i<<1);
}
int ask(int x,int i)
{
if(l[i]==r[i]) return t[i];
pushdown(i);
int mid=l[i]+r[i]>>1;
if(x<=mid) return ask(x,i<<1);
return ask(x,i<<1|1);
}
inline int tree_query(int x,int y)
{
int ans=0;
while(top[x]!=top[y])
{
if(deep[top[x]]<deep[top[y]]) std::swap(x,y);
ans+=query(to[top[x]],to[x],1);
x=fa[top[x]];
}
if(x==y) return ans;
if(deep[x]>deep[y]) std::swap(x,y);
ans+=query(to[x]+1,to[y],1);
return ans;
}
inline void tree_change(int x,int y,int k)
{
while(top[x]!=top[y])
{
if(deep[top[x]]<deep[top[y]]) std::swap(x,y);
change(to[top[x]],to[x],0,k,1);
x=fa[top[x]];
}
if(x==y) return;
if(deep[x]>deep[y]) std::swap(x,y);
change(to[x]+1,to[y],0,k,1);
}
namespace Tarjan
{
int dfn[maxn],low[maxn],st[maxn];
std::set< std::pair<int,int> > s;
int head[maxn];
struct EDGE
{
int v,nxt;
}e[maxn<<3],E[maxn<<3];
int num=0,cnt,mid,top;
inline void add(int x,int y)
{
e[++num].v=y;
e[num].nxt=head[x];
head[x]=num;
}
void tarjan(int x,int fa)
{
st[++top]=x;
dfn[x]=low[x]=++cnt;
for(re int i=head[x];i;i=e[i].nxt)
if(!dfn[e[i].v]) tarjan(e[i].v,x),low[x]=std::min(low[x],low[e[i].v]);
else if(e[i].v!=fa) low[x]=std::min(low[x],dfn[e[i].v]);
if(low[x]==dfn[x])
{
p++;
do
{
mid=st[top--];
belong[mid]=p;
}while(x!=mid);
}
}
void prepare()
{
n=read();
m=read();
for(re int i=1;i<=m;i++)
E[i].v=read(),E[i].nxt=read();
int x,y;
while(1)
{
opt[Q+1]=read();
if(opt[Q+1]==-1) break;
if(opt[Q+1]==1) tot++;
Q++;
xx[Q]=read();
yy[Q]=read();
if(!opt[Q])
{
s.insert(std::make_pair(xx[Q],yy[Q]));
s.insert(std::make_pair(yy[Q],xx[Q]));
}
}
for(re int i=1;i<=m;i++)
if(s.find(std::make_pair(E[i].v,E[i].nxt))==s.end()&&s.find(std::make_pair(E[i].nxt,E[i].v))==s.end())
add(E[i].v,E[i].nxt),add(E[i].nxt,E[i].v);
tarjan(1,0);
for(re int i=1;i<=n;i++)
for(re int j=head[i];j;j=e[j].nxt)
if(belong[i]!=belong[e[j].v]) add_edge(belong[i],belong[e[j].v]);
}
}
int main()
{
Tarjan::prepare();
deep[1]=1;
dfs1(1);
now=tot;
dfs2(1,1);
build(1,p,1);
change(1,1,0,b[1],1);
for(re int T=Q;T;T--)
{
if(opt[T]==1) a[now--]=tree_query(belong[xx[T]],belong[yy[T]]);
else
{
if(ask(to[belong[xx[T]]],1)==ask(to[belong[yy[T]]],1)) continue;
tree_change(belong[xx[T]],belong[yy[T]],++p);
}
}
for(re int i=1;i<=tot;i++)
printf("%d\n",a[i]);
return 0;
}
【[AHOI2005]航线规划】的更多相关文章
- 洛谷 P2542 [AHOI2005]航线规划 解题报告
P2542 [AHOI2005]航线规划 题目描述 对Samuel星球的探险已经取得了非常巨大的成就,于是科学家们将目光投向了Samuel星球所在的星系--一个巨大的由千百万星球构成的Samuel星系 ...
- P2542 【[AHOI2005]航线规划】
P2542 [[AHOI2005]航线规划] 一个无向图,m个操作 删去一条边 给定两个点,求有多少边使得如果这条边不存在,给定的两个点不连通 一般这种删边的题目,考虑逆序加边处理 在删完的图中,任意 ...
- [AHOI2005] 航线规划
Description 对Samuel星球的探险已经取得了非常巨大的成就,于是科学家们将目光投向了Samuel星球所在的星系--一个巨大的由千百万星球构成的Samuel星系. 星际空间站的Samuel ...
- AHOI2005航线规划 bzoj1969(LCT缩点)
题目描述 对Samuel星球的探险已经取得了非常巨大的成就,于是科学家们将目光投向了Samuel星球所在的星系——一个巨大的由千百万星球构成的Samuel星系. 星际空间站的Samuel II巨型计算 ...
- P2542 [AHOI2005]航线规划 LCT维护双连通分量
\(\color{#0066ff}{ 题目描述 }\) 对Samuel星球的探险已经取得了非常巨大的成就,于是科学家们将目光投向了Samuel星球所在的星系--一个巨大的由千百万星球构成的Samuel ...
- 洛谷P2542 [AHOI2005]航线规划(LCT,双连通分量,并查集)
洛谷题目传送门 太弱了不会树剖,觉得LCT好写一些,就上LCT乱搞,当LCT维护双连通分量的练手题好了 正序删边是不好来维护连通性的,于是就像水管局长那样离线处理,逆序完成操作 显然,每个点可以代表一 ...
- 洛谷 P2542 [AHOI2005]航线规划(Link-cut-tree)
题面 洛谷 bzoj 题解 离线处理+LCT 有点像星球大战 我们可以倒着做,断边变成连边 我们可以把边变成一个点 连边时,如果两个点本身不联通,就\(val\)赋为\(1\),并连接这条边 如果,两 ...
- [AHOI2005]航线规划——LCT维护边双联通分量
因为只能支持加入一个边维护边双,所以时光倒流 维护好边双,每次就是提取出(x,y)的链,答案就是链长度-1 具体维护边双的话, void access(int x){ for(reg y=0;x;y= ...
- 洛谷 P2542 [AHOI2005]航线规划 树链剖分_线段树_时光倒流_离线
Code: #include <map> #include <cstdio> #include <algorithm> #include <cstring&g ...
随机推荐
- 管理nginx(采用信号的方式)
启动:sbin/nginx 立即停止:sbin/nginx -s stop 平滑停止:sbin/nginx -s quit 重载配置:sbin/nginx -s reload(不会导致服务器关闭, 而 ...
- C# dynamic json
对应普通对象,写个扩展方法,ToJson蛮方便. 但是 dynamic 类型就不行了,因为是运行时解析,只能转换为强类型 IDictionary<string, object> 才可以. ...
- WPF 字体路径设置
以往在引用电脑里面没有的其它字体,都是需要把这个字体安装到自己电脑中, WPF程序中可以直接把字体文件拷到程序资源目录里面,这样就可以引用的到,不必要非安装这种字体; 下面总结了几种路径的具体方法,测 ...
- Lucence学习之一:全文检索的基本原理
本文转载自: http://www.cnblogs.com/forfuture1978/archive/2009/12/14/1623594.html 一.总论 根据http://lucene.ap ...
- python中的单例模式的应用
1 使用__new__方法 class Singleton(object): def __new__(cls, *args, **kw): if not hasattr(cls, ...
- C10K问题摘要
本文的内容是下面几篇文章阅读后的内容摘要: http://www.kegel.com/c10k.html (英文版) http://www.oschina.net/translate/c10k (中文 ...
- spring实现可重置时间定时器
此文章是基于 搭建Jquery+SpringMVC+Spring+Hibernate+MySQL平台 一. jar包介绍 1. spring-framework-4.3.4.RELEASE 的 lib ...
- App Not Responsing
参见原文:http://rayleeya.iteye.com/blog/1955657 inputDispatchingTimedOut contentProviderNotResponsing se ...
- centos自带python2.6无法使用pip命令
1.首先检查linux有没有安装python-pip包,直接执行 yum install python-pip,或者 which pip 我的已经安装了 2.没有可用软件包 python-pip.就执 ...
- Tomcat添加用户
在conf目录下tomcat-users.xml文件里添加如下代码: <role rolename="manager-gui"/> <user username= ...