因为只能支持加入一个边维护边双,所以时光倒流

维护好边双,每次就是提取出(x,y)的链,答案就是链长度-1

具体维护边双的话,

void access(int x){
for(reg y=0;x;y=x,x=t[y].fa=fin(t[x].fa)){//注意更新
splay(x);rs=y;pushup(x);
}
}

dele(int x,int y)把x节点的father指向y,这个x临死前把信息指到y,以便于后面要找x的直接找y即可。{

  if(x) fa[x]=y,dele(rs,y),dele(ls,y)
}

merge函数(int x,int y){

  if(x==y(在一起))return 什么都不用做

  makert(x)

  if(findrt(y)!=x){

    t[x].fa=y相当于直接link

    return;

  }

  splay(x)

  出环了。那么要缩点,x现在是根,并且作为代表点

  dele(rs,x)

  t[x].ch[1]=0,干掉子树,这个子树已经名存实亡了。

  pushup(x)

}

我通过merge,dele函数打上标记,

在access的时候把标记依次还原,达到真正缩点的目的。

而并查集使我每次都会到真正的节点。不会到已经删除的节点。

代码:

#include<bits/stdc++.h>
#define il inline
#define reg register int
#define numb (ch^'0')
#define ls t[x].ch[0]
#define rs t[x].ch[1]
using namespace std;
typedef long long ll;
il void rd(int &x){
char ch;bool fl=false;
while(!isdigit(ch=getchar()))(ch=='-')&&(fl=true);
for(x=numb;isdigit(ch=getchar());x=x*+numb);
(fl==true)&&(x=-x);
}
namespace Miracle{
const int N=+;
const int M=+;
int n,m;
struct node{
int sz,fa,ch[],r;
}t[N];
int fa[N];
int fin(int x){
return fa[x]==x?x:fa[x]=fin(fa[x]);
}
bool nrt(int x){
return (t[t[x].fa].ch[]==x)||(t[t[x].fa].ch[]==x);
}
void rev(int x){
swap(t[x].ch[],t[x].ch[]);
t[x].r^=;
}
void pushdown(int x){
if(t[x].r){
t[x].r=;
rev(ls);rev(rs);
}
}
void pushup(int x){
t[x].sz=t[ls].sz+t[rs].sz+;
}
void rotate(int x){
int y=t[x].fa,d=t[y].ch[]==x;
t[t[y].ch[d]=t[x].ch[!d]].fa=y;
if(nrt(y)) t[t[x].fa=t[y].fa].ch[t[t[y].fa].ch[]==y]=x;
else t[x].fa=t[y].fa;
t[t[y].fa=x].ch[!d]=y;
pushup(y);
}
int sta[N];
void splay(int x){
int y=x,z=;
sta[++z]=y;
while(nrt(y)) y=t[y].fa,sta[++z]=y;
while(z) pushdown(sta[z--]); while(nrt(x)){
y=t[x].fa,z=t[y].fa;
if(nrt(y)){
rotate(((t[y].ch[]==x)==(t[z].ch[]==y))?y:x);
}
rotate(x);
}
pushup(x);
}
void access(int x){
for(reg y=;x;y=x,x=t[y].fa=fin(t[x].fa)){
splay(x);rs=y;pushup(x);
}
}
void makert(int x){
access(x);splay(x);rev(x);
}
int findrt(int x){
access(x);splay(x);
pushdown(x);
while(t[x].ch[]) pushdown(x=t[x].ch[]);
splay(x);
return x;
}
void dele(int x,int y){
if(x) fa[x]=y,dele(ls,y),dele(rs,y);
}
void merge(int x,int y){
if(x==y) return;
makert(x);
if(findrt(y)!=x){
t[x].fa=y;
pushup(y);
return;
}
dele(t[x].ch[],x);
t[x].ch[]=;
pushup(x);
}
void split(int x,int y){
makert(x);access(y);splay(y);
}
struct edge{
int x,y;
bool friend operator <(edge a,edge b){
if(a.x==b.x) return a.y<b.y;
return a.x<b.x;
}
}e[M];
bool vis[M];
struct que{
int c;
int x,y;
}q[M];
int ans[M],cnt;
int main(){
rd(n);rd(m);
int x,y;
for(reg i=;i<=n;++i){
fa[i]=i;t[i].sz=;
}
for(reg i=;i<=m;++i){
rd(x);rd(y);
if(x>y) swap(x,y);
e[i].x=x;e[i].y=y;
}
sort(e+,e+m+);
int c;
int tot=;
while(){
rd(c);
if(c==-) break;
++tot;
rd(x);rd(y);
if(x>y) swap(x,y);
if(c==){
edge lp;lp.x=x,lp.y=y;
vis[lower_bound(e+,e+m+,lp)-e]=;
}
q[tot].x=x,q[tot].y=y;
q[tot].c=c;
} for(reg i=;i<=m;++i){
if(!vis[i]){
x=fin(e[i].x),y=fin(e[i].y);
merge(x,y);
}
}
for(reg i=tot;i>=;--i){
x=fin(q[i].x);y=fin(q[i].y);
if(q[i].c==){
++cnt;
split(x,y);
ans[cnt]=t[y].sz-;
}
else{
merge(x,y);
}
}
for(reg i=cnt;i>=;--i){
printf("%d\n",ans[i]);
}
return ;
} }
signed main(){
Miracle::main();
return ;
} /*
Author: *Miracle*
Date: 2018/12/19 9:57:28
*/

[AHOI2005]航线规划——LCT维护边双联通分量的更多相关文章

  1. BZOJ 1969 航线规划 - LCT 维护边双联通分量

    Solution 实际上就是查询 $u$ 到 $v$ 路径上 边双的个数 $ -1$. 并且题目仅有删边, 那么就离线倒序添边. 维护 边双 略有不同: 首先需要一个并查集, 记录 边双内的点. 在 ...

  2. P2542 [AHOI2005]航线规划 LCT维护双连通分量

    \(\color{#0066ff}{ 题目描述 }\) 对Samuel星球的探险已经取得了非常巨大的成就,于是科学家们将目光投向了Samuel星球所在的星系--一个巨大的由千百万星球构成的Samuel ...

  3. AHOI2005航线规划 bzoj1969(LCT缩点)

    题目描述 对Samuel星球的探险已经取得了非常巨大的成就,于是科学家们将目光投向了Samuel星球所在的星系——一个巨大的由千百万星球构成的Samuel星系. 星际空间站的Samuel II巨型计算 ...

  4. P2542 【[AHOI2005]航线规划】

    P2542 [[AHOI2005]航线规划] 一个无向图,m个操作 删去一条边 给定两个点,求有多少边使得如果这条边不存在,给定的两个点不连通 一般这种删边的题目,考虑逆序加边处理 在删完的图中,任意 ...

  5. 洛谷 P2542 [AHOI2005]航线规划 解题报告

    P2542 [AHOI2005]航线规划 题目描述 对Samuel星球的探险已经取得了非常巨大的成就,于是科学家们将目光投向了Samuel星球所在的星系--一个巨大的由千百万星球构成的Samuel星系 ...

  6. BZOJ 2959: 长跑 lct 双联通分量 并查集 splay

    http://www.lydsy.com/JudgeOnline/problem.php?id=2959 用两个并查集维护双联通分量的编号和合并. #include<iostream> # ...

  7. LCT 维护边双 / 点双的模板

    用 \(\text{LCT}\) 维护边双的做法是:加入一条非树边时,将这段树上路径合并为一个点代表这个边双,具体实现用并查集合并点,在 \(\text{Splay}\) 与 \(\text{Acce ...

  8. POJ 3694Network(Tarjan边双联通分量 + 缩点 + LCA并查集维护)

    [题意]: 有N个结点M条边的图,有Q次操作,每次操作在点x, y之间加一条边,加完E(x, y)后还有几个桥(割边),每次操作会累积,影响下一次操作. [思路]: 先用Tarjan求出一开始总的桥的 ...

  9. 『Tarjan算法 无向图的双联通分量』

    无向图的双连通分量 定义:若一张无向连通图不存在割点,则称它为"点双连通图".若一张无向连通图不存在割边,则称它为"边双连通图". 无向图图的极大点双连通子图被 ...

随机推荐

  1. Vue简单使用,

    一些零碎的知识点: 在js中变量的声明 有三种方式: let,var, const let: 对应的是一个块级作用域 { let a = 12 } console.log(a) 这是未声明的, var ...

  2. C语言Windows程序开发—Windows窗口样式与常用控件样式【第04天】

    (一)Windows窗口(MDICLIENT)样式介绍 /* Windows窗口样式 */ WS_BORDER //带有边框的窗口 WS_CAPTION //带有标题栏的窗口 WS_CHILD //子 ...

  3. Teen Readers【青少年读者】

    Teen Readers Teens and younger children are reading a lot less for fun, according to a Common Sense ...

  4. kafka topic 完全删除

    kafka topic 完全删除   1.自动删除脚本(得配置server.properties 中 delete.topic.enable=true) ./kafka-topics.sh --zoo ...

  5. Tomcat配置SSL连接

    1.服务器端单项认证 在Tomcat的server.xml文件中,已经提供了现成的配置SSL连接器的代码,只要把<Connector>元素的注释去掉即可: <!—  Define a ...

  6. thrift服务端到客户端开发简单示例

    (1)首先我们在服务器端写个helloworld.thrift文件,如下所示: service HelloWorld{ string ping(1: string name), string getp ...

  7. Git 上传本地仓库到码云

    一.将本地的项目上传到码云 1.码云上创建一个项目 testgit (名字随你) 2.本地创建一个文件夹D:/testgit,然后使用git bash 3.cd 到本地文件夹中D:/testgit 4 ...

  8. 常见bug解析-移动端

    手机测试常见bug解析 1.测试时遇到“手机无响应”? 有以下几个原因: a.手机内存不足 b.android进程之间死锁引起的(就是两个进程之间) c.手机的CPU运行高引起的 可以查看手机的崩溃日 ...

  9. cocos2d-x 粒子系统

    粒子系统是模拟自然界中的一些粒子的物理运动的效果,如烟雾,下雪,下雨,火,爆炸等. 粒子发射模式 粒子系统的发射模式的时候有两种方式:重力模式和半径模式. 粒子系统属性  属性名  行为  模式  d ...

  10. 孤荷凌寒自学python第七十六天开始写Python的第一个爬虫6

    孤荷凌寒自学python第七十六天开始写Python的第一个爬虫6 (完整学习过程屏幕记录视频地址在文末) 今天在上一天的基础上继续完成对我的第一个代码程序的书写. 不过由于对python-docx模 ...