当前位置 : 主页 > 编程语言 > python >

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

来源:互联网 收集:自由互联 发布时间:2023-03-22
E. Xenia and Tree time limit per test memory limit per test input output nnodes. We will consider the tree nodes indexed from 1 ton. We will also consider the first node to be initially painted red, and the other nodes — to be painted blu

E. Xenia and Tree

time limit per test

memory limit per test

input

output

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.

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

    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)

    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 41 22 32 44 52 12 51 22 5

    output

    032

    思路:把查询分成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[n]) 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;}

    网友评论