Xenia the programmer has a tree consisting of n nodes. We will consider the tree nodes indexed from 1 to n. We will also consider the first node to be initially painted red, and the other nodes — to be painted blue.
The distance between two tree nodes v and u is the number of edges in the shortest path between v and u.
Xenia needs to learn how to quickly execute queries of two types:
- paint a specified blue node in red;
- calculate which red node is the closest to the given one and print the shortest distance to the closest red node.
Your task is to write a program which will execute the described queries.
The first line contains two integers n and m (2 ≤ n ≤ 105, 1 ≤ m ≤ 105) — the number of nodes in the tree and the number of queries. Next n - 1 lines contain the tree edges, the i-th line contains a pair of integers ai, bi (1 ≤ ai, bi ≤ n, ai ≠ bi) — an edge of the tree.
Next m lines contain queries. Each query is specified as a pair of integers ti, vi (1 ≤ ti ≤ 2, 1 ≤ vi ≤ n). If ti = 1, then as a reply to the query we need to paint a blue node vi in red. If ti = 2, then we should reply to the query by printing the shortest distance from some red node to node vi.
It is guaranteed that the given graph is a tree and that all queries are correct.
For each second type query print the reply in a single line.
5 4 1 2 2 3 2 4 4 5 2 1 2 5 1 2 2 5
0 32
参考:http://blog.csdn.net/qian99/article/details/20141243
因为变成红色的点不会再变成蓝色,所以某一个点距离最近的红点的距离只会越来越小或者不变,我们用spfa求出每个红点到其他点的最近距离,显然对于每个红点只需要spfa一次,但如果每次加入一个红点都spfa一次,那最坏情况就要有10^5次spfa,所以采取分块的想法(原来这也叫分块),当累计了sqrt(n)个点的时候才spfa一次,查询时,只需要用LCA求一下点到红点的最短距离,注意每次spfa后,要清空红点,因为每个点只需要执行一次spfa;
/* *===================== *File Name:a.cpp *Author: qqspeed *Date: 2014年 07月 18日 星期五 14:41:59 CST *===================== */ #include <stdio.h> #include <string.h> #include <iostream> #include <string> #include <queue> #include <stack> #include <map> #include <math.h> #include <vector> #include <stdlib.h> #include <algorithm> using namespace std; typedef long long ll; #define rep(i,s,t) for(int i=s;i<t;i++) #define red(i,s,t) for(int i=s-1;i>=t;i--) #define ree(i,now) for(int i=head[now];i!=-1;i=edge[i].next) #define clr(a,v) memset(a,v,sizeof a) #define L t<<1 #define R t<<1|1 #define MID int mid=(l+r)>>1 //#define max(a,b) (a<b?b:a) //#define min(a,b) (a<b?a:b) #define SQR(a) ((a)*(a)) inline int input(){ int ret=0;bool isN=0;char c=getchar(); while(c<'0' || c>'9'){ if(c=='-') isN=1; c=getchar(); } while(c>='0' && c<='9'){ ret=ret*10+c-'0'; c=getchar(); } return isN?-ret:ret; } inline void output(int x){ if(x<0){ putchar('-');x=-x; } int len=0,data[11]; while(x){ data[len++]=x%10;x/=10; } if(!len) data[len++]=0; while(len--) putchar(data[len]+48); putchar('\n'); } const int MAXN=100005; int n,m,a,b; int ans[MAXN]; int red[MAXN],red_num; int s; int fa[MAXN][20],dep[MAXN]; bool vis[MAXN]; struct EDGE{ int v,next; }edge[MAXN<<1]; int e,head[MAXN]; inline void addEdge(int u,int v){ edge[e].v=v; edge[e].next=head[u]; head[u]=e++; } inline void dfs(int now,int pre){ dep[now]=dep[pre]+1; fa[now][0]=pre; rep(i,1,20) fa[now][i]=fa[fa[now][i-1]][i-1]; ree(i,now){ int v=edge[i].v; if(v!=pre) dfs(v,now); } } inline int query(int a,int b){ if(dep[a]>dep[b]) swap(a,b); int tx=dep[a],ty=dep[b]; int delta=ty-tx; rep(i,0,20){ if(delta & (1<<i)){ b=fa[b][i]; } } if(a==b) return a; red(i,20,0){ if(fa[a][i] == fa[b][i]) continue; a=fa[a][i]; b=fa[b][i]; } return fa[a][0]; } inline void spfa(){ queue<int>q;clr(vis,0); rep(i,0,red_num){ ans[red[i]]=0; vis[red[i]]=1; q.push(red[i]); } while(!q.empty()){ int now=q.front();q.pop(); vis[now]=0; ree(i,now){ int v=edge[i].v,val=ans[now]+1; if(ans[v]>val){ ans[v]=val; if(!vis[v]){ q.push(v); vis[v]=1; } } } } red_num=0; } int main(){ n=input();m=input();s=(int)(sqrt(n+0.5)); clr(head,-1),e=red_num=0; rep(i,1,n){ a=input(),b=input(); addEdge(a,b),addEdge(b,a); } dep[0]=0; clr(fa[0],0); dfs(1,0); rep(i,1,n+1) ans[i]=(~0U>>2); red[red_num++]=1; spfa(); while(m--){ a=input(),b=input(); if(a==1){ red[red_num++]=b; if(red_num == s){ spfa(); } } else{ int Ans=ans[b]; rep(i,0,red_num){ int lca=query(b,red[i]); Ans=min(Ans,dep[b]+dep[red[i]]-2*dep[lca]); } output(Ans); } } return 0; }