HDU 5967 小R與手機(動態樹)
阿新 • • 發佈:2017-07-25
出現 else rotate bsp 所在 print target light tmp
【題目鏈接】 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與手機(動態樹)