您的位置:首页 > 其它

Hdu 5967 小R与手机

2016-12-04 11:06 344 查看
LCT模板题

如果某一次加边会成环,我们可以保证这个点一定是某一个根,在根上记录一下后继

每一次切断某条边的之后同时查询根的是否有后继,后继是否可以连接

具体见代码

#include<bits/stdc++.h>
using namespace std;

const int maxn = 212345;

struct Node{
int fa,son[2];
int vedg;
void init(){
fa = son[0] = son[1] = 0;
vedg = 0;
}
}node[maxn];

int ori(int st){
if(node[st].fa < 0) return 0;
return st == node[node[st].fa].son[1];
}
void setc(int st,int sn,int d){
if(st > 0) node[st].son[d] = sn;
if(sn > 0) node[sn].fa     = st;
}

void zg(int x){
int st = node[x].fa;
int p = node[st].fa;
int d = ori(x) , dst=ori(st);

setc(st,node[x].son[d^1],d);
setc(x,st,d^1);
setc(p,x,dst);
}

void splay(int x){
#define f(x) (node[x].fa)
while(f(x) > 0) {
if(f(f(x)) <= 0) zg(x);
else{
if(ori(x) == ori(f(x)))
zg(f(x));
else
zg(x);
zg(x);
}
}
}

void access(int x){
splay(x);
while(node[x].fa < 0){
int fa = -node[x].fa;
splay(fa);
node[node[fa].son[1]].fa *= -1;
setc(fa,x,1);
splay(x);
}
}

int root(int x){
access(x);
while(node[x].son[0]) {
x = node[x].son[0];
}
splay(x);
return x;
}

void link(int st,int x){
access(x);
node[x].fa = -st;
access(x);
}
void cut(int x){
access(x);
node[node[x].son[0]].fa = 0;
node[x].son[0] = 0;
}

void Link(int st,int x){
int rot = root(x);
if(rot == x) node[rot].vedg = 0;
else cut(x);
int rv = node[rot].vedg;
if(rv && root(rv) != rot){
link(rv,rot);
node[rot].vedg = 0;
}
if(root(st) == x) node[x].vedg = st;
else link(st,x);
}

int main(){
int n,m;
scanf("%d %d",&n,&m);
for(int i = 0 ; i <= n ; i ++)
node[i].init();
int x;
for(int i = 1; i <= n; i ++){
scanf("%d",&x);
if(x) Link(x,i);
}
int ord,st;
while(m--){
scanf("%d %d",&ord,&x);
if(ord == 2){
x = root(x);
printf("%d\n",node[x].vedg == 0 ? x : -1);
}
else{
scanf("%d",&st);
Link(st,x);
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: