[AHOI2005]航线规划——LCT维护边双联通分量
因为只能支持加入一个边维护边双,所以时光倒流
维护好边双,每次就是提取出(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维护边双联通分量的更多相关文章
- BZOJ 1969 航线规划 - LCT 维护边双联通分量
Solution 实际上就是查询 $u$ 到 $v$ 路径上 边双的个数 $ -1$. 并且题目仅有删边, 那么就离线倒序添边. 维护 边双 略有不同: 首先需要一个并查集, 记录 边双内的点. 在 ...
- P2542 [AHOI2005]航线规划 LCT维护双连通分量
\(\color{#0066ff}{ 题目描述 }\) 对Samuel星球的探险已经取得了非常巨大的成就,于是科学家们将目光投向了Samuel星球所在的星系--一个巨大的由千百万星球构成的Samuel ...
- AHOI2005航线规划 bzoj1969(LCT缩点)
题目描述 对Samuel星球的探险已经取得了非常巨大的成就,于是科学家们将目光投向了Samuel星球所在的星系——一个巨大的由千百万星球构成的Samuel星系. 星际空间站的Samuel II巨型计算 ...
- P2542 【[AHOI2005]航线规划】
P2542 [[AHOI2005]航线规划] 一个无向图,m个操作 删去一条边 给定两个点,求有多少边使得如果这条边不存在,给定的两个点不连通 一般这种删边的题目,考虑逆序加边处理 在删完的图中,任意 ...
- 洛谷 P2542 [AHOI2005]航线规划 解题报告
P2542 [AHOI2005]航线规划 题目描述 对Samuel星球的探险已经取得了非常巨大的成就,于是科学家们将目光投向了Samuel星球所在的星系--一个巨大的由千百万星球构成的Samuel星系 ...
- BZOJ 2959: 长跑 lct 双联通分量 并查集 splay
http://www.lydsy.com/JudgeOnline/problem.php?id=2959 用两个并查集维护双联通分量的编号和合并. #include<iostream> # ...
- LCT 维护边双 / 点双的模板
用 \(\text{LCT}\) 维护边双的做法是:加入一条非树边时,将这段树上路径合并为一个点代表这个边双,具体实现用并查集合并点,在 \(\text{Splay}\) 与 \(\text{Acce ...
- POJ 3694Network(Tarjan边双联通分量 + 缩点 + LCA并查集维护)
[题意]: 有N个结点M条边的图,有Q次操作,每次操作在点x, y之间加一条边,加完E(x, y)后还有几个桥(割边),每次操作会累积,影响下一次操作. [思路]: 先用Tarjan求出一开始总的桥的 ...
- 『Tarjan算法 无向图的双联通分量』
无向图的双连通分量 定义:若一张无向连通图不存在割点,则称它为"点双连通图".若一张无向连通图不存在割边,则称它为"边双连通图". 无向图图的极大点双连通子图被 ...
随机推荐
- 百度app红包? 百度全家桶?果断卸载
听说今年的春晚红包与百度合作.这不 刚又下载了一个百度app,之前下载过,太卡了,用户体验极.本身对百度也没啥好感,再加上这周看了:百度已死的文章,搜索全百家号.具体啥情况,你们百度搜一搜吧
- YII2 多MongoDB配置和使用
1:在config/web.php 文件下配置多个连接即可: 注意在componets 下 'mongodb' => [ 'class' => '\yii\mongodb\Connecti ...
- Java学习笔记一:三步搭建Java开发环境
Java开发环境搭建 一:安装JDK: 1.下载地址:http://www.oracle.com/technetwork/java/javase/downloads 非常显眼的下载界面 2.点击下载后 ...
- matlab-罗曼诺夫斯基准则剔除粗大值
罗曼诺夫斯基准则原理 罗曼诺夫斯基准则又称 t检验准则,其特点是首先删除一个可疑的的测得值,然后按 t分布检验被剔除的测量值是否含有粗大误差 罗曼诺夫斯基准则 1)选取合适的显著度a,选择合适的数 ...
- [Cracking the Coding Interview] 4.4 Check Balanced
Implement a function to check if a binary tree is balanced. For the purpose of this question, a bala ...
- python2.7练习小例子(十九)
19):题目:一球从100米高度自由落下,每次落地后反跳回原高度的一半:再落下,求它在第10次落地时,共经过多少米?第10次反弹多高? #!/usr/bin/python # -*- codi ...
- Python未彻底测试的项目
第一 socket 第二 twisted 第三 tornado 第四 微信网页版本登录 第五:进程,线程,协程间关系 第六:TCP三次握手 第七:堡垒机 第八:重写django admin
- .NET中调用不安全代码
.NET中是不允许不安全的代码的,比如指针等.但有些特殊场合还是需要用到指针,这时候就需要在你的代码块上加上unsafe标签.如: 1: unsafe static void Main( ...
- Android Open Source Projects(汇总与整理)
Android Open Source Projects 目前包括: Android开源项目第一篇——个性化控件(View)篇 包括ListView.ActionBar.Menu.ViewPager ...
- 《百词斩·象形9000》第一册(上) 符号Symbol 1
001-upon prep. 在......上面 Wish upon a star.#对着星星许愿. 002-think V. 想,思索,认为:以为,预料 What do you think?#你认为 ...