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
",query(u));
        else  v=read(),make(u,v);
    }
}





原文地址:https://www.cnblogs.com/Cooook/p/7738522.html