CF342E Xenia and Tree

题目描述

程序员 Xenia 有一棵包含 n n n 个节点的树。我们假设这些树节点从 1 1 1 n n n 编号。最初,第一个节点被涂成红色,其余节点都被涂成蓝色。

两棵树上节点 v v v u u u 之间的距离,指的是它们之间最短路径上经过的边的数量。

Xenia 需要快速地执行两种类型的操作:

  1. 将指定的蓝色节点染成红色;
  2. 查询给定节点距离最近的红色节点,并输出最短距离。

你的任务是编写一个程序,执行上述操作。

输入格式

第一行包含两个整数 n n n m m m ( 2 ≤ n ≤ 10 5 ,   1 ≤ m ≤ 10 5 ) (2 \leq n \leq 10^{5},\ 1 \leq m \leq 10^{5}) (2n105, 1m105) —— 树的节点数和操作数。接下来 n − 1 n-1 n1 行每行两个整数 a i , b i a_i, b_i ai,bi ( 1 ≤ a i , b i ≤ n , a i ≠ b i ) (1 \leq a_i, b_i \leq n, a_i \ne b_i) (1ai,bin,ai=bi),表示树中的一条边。

接下来的 m m m 行,每行描述一个操作。每个操作包含两个整数 t i , v i t_i, v_i ti,vi ( 1 ≤ t i ≤ 2 , 1 ≤ v i ≤ n ) (1 \leq t_i \leq 2, 1 \leq v_i \leq n) (1ti2,1vin)。如果 t i = 1 t_i = 1 ti=1,则表示将编号 v i v_i vi 的蓝色节点染成红色。如果 t i = 2 t_i = 2 ti=2,则需要输出编号 v i v_i vi 的节点到距离它最近的红色节点的最短距离。

保证给定的图是树,且所有的操作都是合法的。

输出格式

对于每个第二类型的操作,输出一行,表示最近红色节点到 v i v_i vi 的最短距离。

输入输出样例 #1

输入 #1

5 4
1 2
2 3
2 4
4 5
2 1
2 5
1 2
2 5

输出 #1

0
3
2

说明/提示

由 ChatGPT 5 翻译

思路

分块即可。

代码

#include<bits/stdc++.h>
using namespace std;
long long n,m,uu,vv,tt,f[100005][21],g[100005][21],de[100005],wd[100005],wec=0,oi=1e9+7,qs[100005];
struct one{
    long long t,v;
}u[100005];
struct two{
    long long a,v;
};
bool operator<(two a1,two b1){
    if(a1.v!=b1.v){
        return a1.v>b1.v;
    }
    else{
        return a1.a<b1.a;
    }
}
bool operator>(two a1,two b1){
    if(a1.v!=b1.v){
        return a1.v<b1.v;
    }
    else{
        return a1.a>b1.a;
    }
}
vector<long long> v[100005];
void abc(long long a1,long long b1){
    f[a1][0]=b1;
    g[a1][0]=1;
    de[a1]=de[b1]+1;
    for(int i=0;i<v[a1].size();i++){
        long long tt=v[a1][i];
        if(tt!=b1){
            abc(tt,a1);
        }
    }
    return ;
}
long long bcd(long long a1,long long b1){
    long long c1=0;
    if(de[b1]>=de[a1]){
        swap(a1,b1);
    }
    for(int i=20;i>=0;i--){
        if(de[f[a1][i]]>=de[b1]){
            c1+=g[a1][i];
            a1=f[a1][i];
        }
    }
    if(a1==b1){
        return c1;
    }
    else{
        for(int i=20;i>=0;i--){
            if(f[a1][i]!=f[b1][i]){
                c1+=g[a1][i];
                c1+=g[b1][i];
                a1=f[a1][i];
                b1=f[b1][i];
            }
        }
        return c1+2;
    }
}
priority_queue<two> q;
int main(){
    cin>>n>>m;
    wec=sqrt(m);
    for(int i=1;i<=n;i++){
        v[i].clear();
    }
    for(int i=1;i<=n;i++){
        wd[i]=1e9+7;
    }
    for(int i=1;i<=n-1;i++){
        cin>>uu>>vv;
        v[uu].push_back(vv);
        v[vv].push_back(uu);
    }
    abc(1,0);
    for(int j=1;j<=20;j++){
        for(int i=1;i<=n;i++){
            f[i][j]=f[f[i][j-1]][j-1];
            g[i][j]=g[i][j-1]+g[f[i][j-1]][j-1];
        }
    }
        for(int l=1;l<=n;l++){
            if(l==1){
                wd[1]=0;
                q.push({1,0});
            }
        }
        for(int l=1;l<=n;l++){
            qs[l]=0;
        }
        while(q.size()!=0){
            two a1=q.top();
            q.pop();
            if(qs[a1.a]==1){
                continue;
            }
            else{
                qs[a1.a]=1;
                for(int l=0;l<v[a1.a].size();l++){
                    long long tt=v[a1.a][l];
                    if(wd[tt]>=a1.v+1+1){
                        wd[tt]=a1.v+1;
                        q.push({tt,a1.v+1});
                    }
                }
            }
        }
    for(int i=1,j=1;i<=m;){
        j=1;
        for(int l=1;l<=wec;l++){
            u[l].t=0;
        }
        for(;j<=wec&&i<=m;j++){
            cin>>u[j].t>>u[j].v;
            i++;
        }
        for(int l=1;l<=j;l++){
            if(u[l].t==2){
                oi=wd[u[l].v];
                for(int r=1;r<=l-1;r++){
                    if(u[r].t==1){
                        oi=min(oi,bcd(u[l].v,u[r].v));
                    }
                }
                cout<<oi<<'\n';
            }
        }
        for(int l=1;l<=j;l++){
            if(u[l].t==1){
                wd[u[l].v]=0;
                q.push({u[l].v,0});
            }
        }
        for(int l=1;l<=n;l++){
            qs[l]=0;
        }
        while(q.size()!=0){
            two a1=q.top();
            q.pop();
            if(qs[a1.a]==1){
                continue;
            }
            else{
                qs[a1.a]=1;
                for(int l=0;l<v[a1.a].size();l++){
                    long long tt=v[a1.a][l];
                    if(wd[tt]>=a1.v+1+1){
                        wd[tt]=a1.v+1;
                        q.push({tt,a1.v+1});
                    }
                }
            }
        }
    }
	return 0;
}

更多推荐