HDU 5967 小R与手机(动态树)

【题目链接】 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;
}
时间: 2024-07-30 13:44:57

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

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

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4010 题意; 先给你一棵树,有 \(4\) 种操作: 1.如果 \(x\) 和 \(y\) 不在同一棵树上则在\(x-y\)连边. 2.如果 \(x\) 和 \(y\) 在同一棵树上并且 \(x!=y\) 则把 \(x\) 换为树根并把 \(y\) 和 \(y\) 的父亲分离. 3.如果 \(x\) 和 \(y\) 在同一棵树上则 \(x\) 到 \(y\) 的路径上所有的点权值\(+w\). 4

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

题意: ①首先定义S为一个有序序列,S={ A1 , A2 , A3 , ... , An },n为元素个数 : ②然后定义Sub为S中取出的一个子序列,Sub={ Ai1 , Ai2 , Ai3 , ... , Aim },m为元素个数 : ③其中Sub满足 Ai1 < Ai2 < Ai3 < ... < Aij-1 < Aij < Aij+1 < ... < Aim : ④同时Sub满足对于任意相连的两个Aij-1与Aij都有 ij - ij-1 >

HDU 4010 Query on The Trees(动态树)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4010 题意:一棵树,四种操作: (1)若x和y不在一棵树上,将x和y连边: (2)若x和y在一棵树上,将x变成树根,将y从x树上分离: (3)若x和y在一棵树上,将x到y路径上的所有值增加det: (4)若x和y在一棵树上,输出x到y路径上的最大值. 思路:1操作用link维护,2操作用cut,34操作先split(x,y),然后对y做tag,并且记录路径的max值. 1 #include<iost

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

Query on The Trees Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65768/65768 K (Java/Others)Total Submission(s): 4091    Accepted Submission(s): 1774 Problem Description We have met so many problems on the tree, so today we will have a que

hdu 5398 动态树LCT

GCD Tree Time Limit: 5000/2500 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 415    Accepted Submission(s): 172 Problem Description Teacher Mai has a graph with n vertices numbered from 1 to n. For every edge(u,v),

hdu 4893 Wow! Such Sequence!(线段树功能:单点更新,区间更新相邻较小斐波那契数)

转载请注明出处:http://blog.csdn.net/u012860063?viewmode=contents 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4893 --------------------------------------------------------------------------------------------------------------------------------------------

HDU 4836 The Query on the Tree lca || 欧拉序列 || 动态树

lca的做法还是很明显的,简单粗暴, 不过不是正解,如果树是长链就会跪,直接变成O(n).. 最后跑的也挺快,出题人还是挺阳光的.. 动态树的解法也是听别人说能ac的,估计就是放在splay上剖分一下,做法还是比较复杂的,,, 来一发lca: #include <stdio.h> #include <iostream> #include <algorithm> #include <sstream> #include <stdlib.h> #inc

hdu 5002 (动态树lct)

Tree Time Limit: 16000/8000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 920    Accepted Submission(s): 388 Problem Description You are given a tree with N nodes which are numbered by integers 1..N. Each node is a

hdu 5314 动态树

Happy King Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)Total Submission(s): 821    Accepted Submission(s): 179 Problem Description There are n cities and n−1 roads in Byteland, and they form a tree. The citie