CF 342E Xenia and Tree(分块)

题意:给出一棵树,最开始结点1为红色,其他点为蓝色。有两种操作,一种是把某个结点变为红色,另一种是查询某个点与这个点最近的红色结点的距离。

思路:这题感觉纠结了好久。。。其实利用分块的方法非常简单粗暴,用mind[u]表示距离u最近的红点的距离,把第一个操作分块,每次执行第一个操作时把这个点存下来,当点的数量到达sqrt(m)时,利用bfs更新点到最近红点的距离。查询时,结果为保存的点和查询点的距离的和mind[u]的较小值。


代码:


#include <iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<vector>
#define inf 0x3f3f3f3f
#define Inf 0x3FFFFFFFFFFFFFFFLL
#define eps 1e-9
#define pi acos(-1.0)
using namespace std;
typedef long long ll;
const int maxn=100000+10;
struct Edge
{
    int v,next;
    Edge(){}
    Edge(int v,int next):v(v),next(next){}
}edges[maxn<<1];
int head[maxn],nEdge;
int d[maxn],mind[maxn],pa[maxn][22];
vector<int>rednode;
void AddEdges(int u,int v)
{
    edges[++nEdge]=Edge(v,head[u]);
    head[u]=nEdge;
    edges[++nEdge]=Edge(u,head[v]);
    head[v]=nEdge;
}
void Init()
{
    memset(head,0xff,sizeof(head));
    memset(pa,0,sizeof(pa));
    memset(mind,0x3f,sizeof(mind));
    d[1]=0;nEdge=-1;
}
void dfs(int u,int fa)
{
    for(int k=head[u];k!=-1;k=edges[k].next)
    {
        int v=edges[k].v;
        if(v==fa) continue;
        pa[v][0]=u;
        d[v]=d[u]+1;
        dfs(v,u);
    }
}
void lca_Init(int n)
{
    for(int i=1;i<=20;++i)
        for(int j=1;j<=n;++j)
            pa[j][i]=pa[pa[j][i-1]][i-1];
}
int Lca(int x,int y)
{
    if(x==y) return x;
    if(d[x]>d[y]) swap(x,y);
    for(int i=20;i>=0;--i)
        if(d[pa[y][i]]>d[x]) y=pa[y][i];
    if(pa[y][0]==x) return x;
    if(d[y]>d[x]) y=pa[y][0];
    for(int i=20;i>=0;--i)
    {
        if(pa[y][i]!=pa[x][i])
        {
            y=pa[y][i];
            x=pa[x][i];
        }
    }
    return pa[x][0];
}
void bfs()
{
    queue<int>q;
    int sz=rednode.size();
    for(int i=0;i<sz;++i)
    {
        int v=rednode[i];
        q.push(v);mind[v]=0;
    }
    while(!q.empty())
    {
        int u=q.front();q.pop();
        for(int k=head[u];k!=-1;k=edges[k].next)
        {
            int v=edges[k].v;
            if(mind[v]>mind[u]+1)
            {
                mind[v]=mind[u]+1;
                q.push(v);
            }
        }
    }
    rednode.clear();
}
int main()
{
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    int n,m,u,v;
    scanf("%d%d",&n,&m);
    Init();
    for(int i=1;i<n;++i)
    {
        scanf("%d%d",&u,&v);
        AddEdges(u,v);
    }
    dfs(1,-1);
    lca_Init(n);
    rednode.clear();
    rednode.push_back(1);
    bfs();
    int size=sqrt(m)+1,cnt=0;
    while(m--)
    {
        scanf("%d%d",&u,&v);
        if(u==1)
        {
            rednode.push_back(v);
            cnt++;
            if(cnt==size)
            {
                bfs();
                cnt=0;
            }
        }
        else
        {
            int sz=rednode.size();
            int ans=mind[v];
            for(int i=0;i<sz;++i)
            {
                u=rednode[i];
                int anc=Lca(u,v);
                ans=min(ans,d[u]+d[v]-2*d[anc]);
            }
            printf("%d\n",ans);
        }
    }
    return 0;
}

你可能感兴趣的:(DataStruct)