【题目链接】 http://acm.hdu.edu.cn/showproblem.php?pid=5967

【题目大意】

  给出一张图,每个点仅连一条有向边,或者不连,
  要求查询在可更改有向边的情况每个点通过有向边最终能到的终点,
  如果是个环则输出-1

【题解】

  我们用lct维护,同时在每棵树根结点的位置标记环,
  因为出现环一定在根节点,否则的话只是换直接父节点而不成环,
  对于换直接父节点的操作,我们看该树的根是否有标记,
  如果有则需要在cutf之后重新构建这棵树的根,
  如果换的父节点为自己的子节点,那么就另成一棵树并标记环,

【代码】

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N=200010;
namespace Link_Cut_Tree{
int f[N],son[N][2],val[N],sum[N],tmp[N],Xor[N];bool rev[N];
void Initialize(){
memset(f,0,sizeof(f));
memset(son,0,sizeof(son));
memset(val,0,sizeof(val));
memset(rev,0,sizeof(rev));
}
bool isroot(int x){return !f[x]||son[f[x]][0]!=x&&son[f[x]][1]!=x;}
void rev1(int x){if(!x)return;swap(son[x][0],son[x][1]);rev[x]^=1;}
void pb(int x){if(rev[x])rev1(son[x][0]),rev1(son[x][1]),rev[x]=0;}
void rotate(int x){
int y=f[x],w=son[y][1]==x;
son[y][w]=son[x][w^1];
if(son[x][w^1])f[son[x][w^1]]=y;
if(f[y]){
int z=f[y];
if(son[z][0]==y)son[z][0]=x;else if(son[z][1]==y)son[z][1]=x;
}f[x]=f[y];f[y]=x;son[x][w^1]=y;
}
void splay(int x){
int s=1,i=x,y;tmp[1]=i;
while(!isroot(i))tmp[++s]=i=f[i];
while(s)pb(tmp[s--]);
while(!isroot(x)){
y=f[x];
if(!isroot(y)){if((son[f[y]][0]==y)^(son[y][0]==x))rotate(x);else rotate(y);}
rotate(x);
}
}
void access(int x){for(int y=0;x;y=x,x=f[x])splay(x),son[x][1]=y;}
// 查询x所在的树的根
int root(int x){access(x);splay(x);while(son[x][0])x=son[x][0];return x;}
// 使x成为根
void makeroot(int x){access(x);splay(x);rev1(x);}
// 将x和y所属树合并
void link(int x,int y){makeroot(x);f[x]=y;access(x);}
// 将x和其父节点分开
void cutf(int x){access(x);splay(x);f[son[x][0]]=0;son[x][0]=0;}
// 将边x-y切断
void cut(int x,int y){makeroot(x);cutf(y);}
// 查询x到y的链和
int ask(int x,int y){makeroot(x);access(y);splay(y);return sum[y];}
// 计算x到y的xor和
int xorsum(int x,int y){makeroot(x);access(y);splay(y);return Xor[y];}
// 查询节点到根的距离
int query(int x){access(x);splay(x);return sum[x];}
// 将x为下标的值改为y
int change(int x,int y){makeroot(x);val[x]=y;}
// 将x的父亲改为y
int changef(int x,int y){cutf(x);f[x]=y;}
}
int mark[N];
void Link(int x,int y){
using namespace Link_Cut_Tree;
int rx=root(x);
if(rx==x)mark[x]=0;
else cutf(x);
if(mark[rx]&&root(mark[rx])!=rx){
changef(rx,mark[rx]);
mark[rx]=0;
}if(root(y)==x)mark[x]=y;
else changef(x,y);
}
int n,m,op,x;
int main(){
scanf("%d%d",&n,&m);
using namespace Link_Cut_Tree;
Initialize();
for(int i=1;i<=n;i++){
scanf("%d",&x);
if(x)Link(i,x);
}
while(m--){
scanf("%d%d",&op,&x);
if(op==2){
x=root(x);
printf("%d\n",mark[x]==0?x:-1);
}else{
int y;
scanf("%d",&y);
Link(x,y);
}
}return 0;
}

HDU 5967 小R与手机(动态树)的更多相关文章

  1. HDU 4010 Query on The Trees (动态树)(Link-Cut-Tree)

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4010 题意; 先给你一棵树,有 \(4\) 种操作: 1.如果 \(x\) 和 \(y\) 不在同一 ...

  2. 小R与手机

    Description 小R有n部手机,为了便于管理,他对一些手机设置了"呼叫转移"的功能. 具体来说,第 i(1≤i≤n) 部手机有个参数 ai(0≤ai≤n,ai≠i) .若 ...

  3. HDU 4010 Query on The Trees(动态树)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4010 题意:一棵树,四种操作: (1)若x和y不在一棵树上,将x和y连边: (2)若x和y在一棵树上, ...

  4. hdu 4521 小明序列(线段树,DP思想)

    题意: ①首先定义S为一个有序序列,S={ A1 , A2 , A3 , ... , An },n为元素个数 : ②然后定义Sub为S中取出的一个子序列,Sub={ Ai1 , Ai2 , Ai3 , ...

  5. Hdu 4010-Query on The Trees LCT,动态树

    Query on The Trees Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65768/65768 K (Java/Othe ...

  6. HDU 2475 BOX 动态树 Link-Cut Tree

    Box Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) [Problem De ...

  7. hdu 5398 动态树LCT

    GCD Tree Time Limit: 5000/2500 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Su ...

  8. hdu 5002 (动态树lct)

    Tree Time Limit: 16000/8000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submi ...

  9. hdu 5314 动态树

    Happy King Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)Tot ...

随机推荐

  1. Mac 上真机调试cocos2d-x-3.16的test程序

    文章比较长,一个算是新手又不是新手的程序员的解决过程. 一 xcode中打开项目 首先,下载完成cocos2d-x-3.16之后,解压,然后在根目录build目录下双击cocos2d_tests.xc ...

  2. Vuejs - 单文件组件

    为什么需要单文件组件 在之前的实例中,我们都是通过 Vue.component 或者 components 属性的方式来定义组件,这种方式在很多中小规模的项目中还好,但在复杂的项目中,下面这些缺点就非 ...

  3. POJ 1064 Cable master (二分查找)

    题目链接 Description Inhabitants of the Wonderland have decided to hold a regional programming contest. ...

  4. mssql手工注入2

    --+ 先说一些函数的说明: substring(str,start,len) 截取字符串的作用,第一个参数为要截取的字符串,第二个参数为从哪里开始截取,第三个参数为截取的长度 ascii(char) ...

  5. C++学习之路(七):以const,enum,inline替换#define

    这篇博文主要是编程中的一些问题和技巧.如题目所示,这些关键字的作用不再进行描述.直接描述功能和实例代码. 首先,在头文件中对类进行定义,是不会为类分配内存空间的,在这一点上类定义可以和普通变量类型的声 ...

  6. 用__builtin_return_address获得程序运行栈情况【转】

    转自:http://blog.csdn.net/vpwork/article/details/7680102 %pF versatile_init+0x0/0x110 %pf versatile_in ...

  7. C# 对后台方法事件,可以直接return; 跳出

    protected void lbtButton_Click(object sender, EventArgs e) { return; } C# 对后台方法事件,可以直接return; 跳出

  8. UVA 11076 Add Again

    题目链接:UVA-33478 题意为给定n个数,求这n个数能组成的所有不同的排列组成的数字的和. 思路:发现对于任意一个数字,其在每一位出现的次数是相同的.换言之,所有数字的每一位相加的和是相同的. ...

  9. 设计模式之笔记--原型模式(Prototype)

    原型模式(Prototype) 定义 原型模式(Prototype),用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象. 类图 描述 提供一个克隆自身的接口--Clone方法. 应用场景 ...

  10. 利用python对WiderFace数据解析及画框

    #注:此代码稍作修改也可以用于WFLW人脸数据集的标注文件解析,#参见其README.md文件了解其每一行的信息,从中解析出相应字#段即可. import os import cv2 def draw ...