您的位置:首页 > 其它

Codeforce 342E - Xenia and Tree(LCA+spfa,5级)

2013-09-13 21:10 357 查看
E. Xenia and Tree

time limit per test
5 seconds

memory limit per test
256 megabytes

input
standard input

output
standard output

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.

Input

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.

Output

For each second type query print the reply in a single line.

Sample test(s)

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


output
0
3
2


思路:把查询分成sqrt(m)个块,每个块进行LCA查询,当节点达到 sqrt(m)执行一次最短路。

复杂度<sqrt(m)*m;

#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
#include<cmath>
#define FOR(i,a,b) for(int i=a;i<=b;++i)
#define clr(f,z) memset(f,z,sizeof(f))
#define ll(x) (1<<x)
using namespace std;
const int msize=4e5+9;
const int oo=1e9;
int head[msize],edge;
int to[msize],rmq[msize][33];
bool vis[msize];
int n,m;
queue<int>Q;
class Edge
{
public:int v,next;
}e[msize+msize];
void data()
{
clr(head,-1);edge=0;
}
void add(int u,int v)
{
e[edge].v=v;e[edge].next=head[u];head[u]=edge++;
}
int dep[msize],dfs_clock,e_c[msize],dis[msize];
void dfs(int u,int dd)
{
dep[u]=dd;
to[dfs_clock]=u;
e_c[u]=dfs_clock++;
int v;
for(int i=head[u];~i;i=e[i].next)
{
v=e[i].v;
if(e_c[v]==-1)
{
dfs(v,dd+1);
to[dfs_clock++]=u;
}
}
}
int bit[msize];
void initRMQ()
{
bit[0]=-1;
int n=dfs_clock;
FOR(i,1,n)bit[i]=(i&(i-1))==0?bit[i-1]+1:bit[i-1];
FOR(i,0,n-1)rmq[i][0]=dep[ to[i] ];
FOR(i,1,bit
)
for(int j=0;j+ll(i)-1<n;++j)
rmq[j][i]=min(rmq[j][i-1],rmq[j+ll(i-1)][i-1]);
}
int RMQ(int l,int r)
{ l=e_c[l];r=e_c[r];
if(l>r)swap(l,r);
int t=bit[r-l+1];
r-=ll(t)-1;
return min(rmq[l][t],rmq[r][t]);
}
void getclear()
{
dfs_clock=0;
clr(e_c,-1);
clr(dis,0x3f);
}

void spfa()
{
clr(vis,0);
int u,v;
while(!Q.empty())
{
u=Q.front();Q.pop();vis[u]=0;
for(int i=head[u];~i;i=e[i].next)
{
v=e[i].v;
if(dis[v]>dis[u]+1)
{
dis[v]=dis[u]+1;
if(!vis[v])
{
Q.push(v);
vis[v]=1;
}
}
}
}
}
int getdis(int l,int r)
{
int lca=RMQ(l,r);
// printf("e=%d %d\ne=%d %d\nlca=%d\n",l,dep[l],r,dep[r],lca);
return dep[l]+dep[r]-lca*2;
}
int main()
{ int a,b;
while(~scanf("%d%d",&n,&m))
{ data();
FOR(i,2,n)
{
scanf("%d%d",&a,&b);
add(a,b);add(b,a);
}
int block=sqrt(m);
getclear();
dfs(1,0);
initRMQ();
Q.push(1);
dis[1]=0;
// puts("+++");
FOR(i,1,m)
{
scanf("%d%d",&a,&b);
if(a==1)
{
Q.push(b);dis[b]=0;
}
else if(a==2)
{ int sz=Q.size();
if(sz>block)
{
spfa();
printf("%d\n",dis[b]);
}
else
{
int ans=dis[b];
int bg=-1;
while(!Q.empty())
{
int q=Q.front();
if(bg==-1)bg=q;
else if(bg==q)break;
Q.pop();
// puts("_+)+");
// printf("d=%d %d\n",b,q);
ans=min(ans,getdis(b,q));
Q.push(q);
}
printf("%d\n",ans);
}
}
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: