BZOJ 3319 黑白树
题目描述
给定一棵树,边的颜色为黑或白,初始时全部为白色。维护两个操作:
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); } }