Description
给定一棵树,边的颜色为黑或白,初始时全部为白色。维护两个操作:
1.查询u到根路径上的第一条黑色边的标号。
2.将u到v 路径上的所有边的颜色设为黑色。
Notice:这棵树的根节点为1
Input
第一行两个数n,m分别表示点数和操作数。
接下来n-? 1行,每行2个数u,v.表示一条u到v的边。
接下来m行,每行为以下格式:
1 v 表示第一个操作
2 v u 表示第二种操作
Output
对于每个询问,输出相应答案。如果不存在,输出0。
Sample Input
5 4
1 2
1 3
2 4
2 5
1 2
2 2 3
1 3
1 4
Sample Output
0
2
1
HINT
对于 100% 的数据:n,m<=10^6
分析:可以把白边的两个点并起来,这样找路径可以直接find找到。可以直接树剖
代码:
/**************************************************************
Problem: 3319
User: beginend
Language: C++
Result: Accepted
Time:8196 ms
Memory:78052 kb
****************************************************************/
#include <iostream>
#include <cstdio>
#include <algorithm>
const int maxn=1e6+1;
const int inf=0x3f3f3f3f;
using namespace std;
struct node{
int x,y,next;
}adge[maxn*2];
struct ques{
int id,x,ans;
}q[maxn];
struct kc{
int x,y,time;
}c[maxn];
int n,m,i,x,y,cnt,num,sz,op,j;
int p[maxn],dep[maxn],fa[maxn],f[maxn],ls[maxn];
void add(int x,int y)
{
adge[++cnt].x=x;
adge[cnt].y=y;
adge[cnt].next=ls[x];
ls[x]=cnt;
}
void dfs(int x,int fat)
{
fa[x]=fat;
dep[x]=dep[fat]+1;
for (int t=ls[x];t>0;t=adge[t].next)
{
int y=adge[t].y;
if (fa[x]==y) continue;
f[y]=(t+1)/2;
dfs(y,x);
}
}
int find(int x)
{
int root,w,y=x;
while (p[y]>0) y=p[y];
root=y;
y=x;
while (p[y]>0)
{
w=p[y];
p[y]=root;
y=w;
}
return root;
}
void uni(int u,int v)
{
int x=find(u);
int y=find(v);
if (x!=y) p[y]=x;
}
void change(int u,int v,int ti)
{
x=find(u); y=find(v);
while (x!=y)
{
if (dep[x]>dep[y]) swap(x,y);
c[++num].x=fa[y];
c[num].y=y;
c[num].time=ti;
uni(fa[y],y);
x=find(x);y=find(y);
}
}
int main()
{
scanf("%d%d",&n,&m);
for (i=1;i<n;i++)
{
scanf("%d%d",&x,&y);
add(x,y);
add(y,x);
}
dfs(1,0);
sz=cnt;cnt=num=0;
for (i=1;i<=m;i++)
{
scanf("%d",&op);
if (op==1)
{
scanf("%d",&x);
q[++cnt].id=i;
q[cnt].x=x;
}
else
{
scanf("%d%d",&x,&y);
change(x,y,i);
}
}
for (i=1;i<=sz;i=i+2)
{
if (find(adge[i].x)!=find(adge[i].y))
{
if (dep[adge[i].x]>dep[adge[i].y]) swap(adge[i].x,adge[i].y);
c[++num].x=adge[i].x;
c[num].y=adge[i].y;
c[num].time=inf;
}
}
for (i=1;i<=n;i++) p[i]=0;
j=num;
for (i=cnt;i>0;i--)
{
while (q[i].id<c[j].time)
{
uni(c[j].x,c[j].y);
j--;
}
q[i].ans=f[find(q[i].x)];
}
for (i=1;i<=cnt;i++) printf("%d\n",q[i].ans);
}