题目描述
给定一棵树,边的颜色为黑或白,初始时全部为白色。维护两个操作:
1.查询u到根路径上的第一条黑色边的标号。
2.将u到v 路径上的所有边的颜色设为黑色。
Notice:这棵树的根节点为1
输入
第一行两个数n,m分别表示点数和操作数。
接下来n-? 1行,每行2个数u,v.表示一条u到v的边。
接下来m行,每行为以下格式:
1 v 表示第一个操作
2 v u 表示第二种操作
输出
对于每个询问,输出相应答案。如果不存在,输出0。
样例输入
5 4
1 2
1 3
2 4
2 5
1 2
2 2 3
1 3
1 4
样例输出
0
2
1
这题ryf在考试暴力水之,woc了,想要树剖水之,码码码了一小时然后0,什么毒瘤题,,,卡树剖,卡LCT(心疼一发wq)卡正解,不卡暴力!!这题有问题???
暴力code:
#define MAXN 3000005
#include <iostream>
#include <cstring>
#include <stdio.h>
#define fin fil
using namespace std;
int n,m,first[MAXN],e=1,deep[MAXN],f[MAXN],id[MAXN];
bool vis[MAXN],color[MAXN];
int read(){
int x=0;
char ch=getchar();
for(;ch>'9'||ch<'0';ch=getchar());
for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+(ch^48);
return x;
}
struct edge{
int u,v,next,id;
}a[MAXN<<1];
void push(int u,int v,int id){
a[e].u=u;
a[e].v=v;
a[e].id=id;
a[e].next=first[u];
first[u]=e++;
}
void dfs(int u){
vis[u]=1;
for(int i=first[u];i;i=a[i].next){
int v = a[i].v;
if(vis[v])continue;
deep[v]=deep[u]+1;
id[v]=a[i].id;
f[v]=u;dfs(v);
}
}
int query(int u){
while(u!=1){
if(color[u])return id[u];
else u=f[u];
}
return 0;
}
void make(int u,int v){
if(deep[u]>deep[v])swap(u,v);
while(deep[u]<deep[v]){
color[v]=1;
v=f[v];
}
if(u==v)return;
while(u!=v){
color[u]=1;
color[v]=1;
u=f[u];v=f[v];
}
}
int main(){
n=read();m=read();
for(int i=1;i<n;i++){
int u,v;
u=read();v=read();
push(u,v,i);push(v,u,i);
}
deep[1]=1;
dfs(1);
while(m--){
int op,u,v;
op=read();u=read();
if(op==1)printf("%d\n",query(u));
else v=read(),make(u,v);
}
}