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

维护好边双,每次就是提取出(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. Hadoop(4)-Hadoop集群环境搭建

    准备工作 开启全部三台虚拟机,确保hadoop100的机器已经配置完成 分发脚本 操作hadoop100 新建一个xsync的脚本文件,将下面的脚本复制进去 vim xsync #这个脚本使用的是rs ...

  2. VSCode插件整理

    VSCode插件整理 VSCode插件整理 官网地址 vscode常用配置(User Settings文件) 基本插件 前端插件 VUE部分 python MarkDown部分 连接Linux 本地与 ...

  3. Qt on Android 蓝牙通信开发

    版权声明:本文为MULTIBEANS ORG研发跟随文章,未经MLT ORG允许不得转载. 最近做项目,需要开发安卓应用,实现串口的收发,目测CH340G在安卓手机上非常麻烦,而且驱动都是Java版本 ...

  4. Python的scrapy学习心得

    scrapy框架是Python爬虫的一个使用起来不错的框架,通过这个框架可以很快的爬出自己想要的数据 官方的定义是如下的图片,其实看不太懂 在平常使用这个框架的时候,主要用三部分,spider爬虫主体 ...

  5. Python学习 :深浅拷贝

    深浅拷贝 一.浅拷贝 只拷贝第一层数据(不可变的数据类型),并创建新的内存空间进行储蓄,例如:字符串.整型.布尔 除了字符串以及整型,复杂的数据类型都使用一个共享的内存空间,例如:列表 列表使用的是同 ...

  6. 模块导入应用settings的字符串

    看django源码,感觉他的settings好高大上然后自己试试 以上是文件目录 email.py中代码 class Email: def send(self): print('发送email') M ...

  7. HDU暑假多校第八场J-Taotao Picks Apples

    一.题意 给定一个序列,之后给出若干个修改,修改的内容为在原序列的基础上,将某一位元素的值改成给定的值<每次修改相互独立,不保存修改后的结果>.之后询问,在选择第一位元素的情况下,最长递增 ...

  8. Eclipse_安装SAP_HANA数据库插件

    1.对于Eclipse Oxygen,请添加URL https://tools.hana.ondemand.com/oxygen 2.对于Eclipse luna,请添加URL     https:/ ...

  9. jquery validation remote进行唯一性验证时只使用自定义参数,不使用默认参数

    在使用validation进行唯一性验证时,想各个模块写一个统一的方法,相统一参数名称,但是remote方法会默认把对应的参数传过去 如: 会把role.roleName默认作为变量提交过去 所以想自 ...

  10. Uber CEO博鳌论坛采访:看好中国市场共享经济的发展模式

    滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://www.cnblogs.com/mfry ...