cf 832D Misha, Grisha and Underground 【lca+倍增】

来源:互联网 发布:mx anywhere2 软件 编辑:程序博客网 时间:2024/06/07 06:51




点击打开链接



题意:


           给你一个树,再给你三个点,然后问你任意两个点到另外一个点中间经过的相同的节点最大个数。



题解:


         照题解上面,求出任意两个点的公共祖先,保留深度最大的那一个。该点即为三个点的交汇点。

         然后求出交汇点到三点的最大距离即为答案。

下面附上官方题解:

Let vertex 1 be the root of the tree. For each vertex i we calculate value hi  — distance to the root.

Now we can represent way v1  v2 as two ways v1  lca(v1, v2) and lca(v1, v2)  v2.

Note that number of edges in the interseption of two such ways v1  v2 и u1  u2hv1 ≤ hv2hu1 ≤ hu2 is max(0, hlca(u2, v2) - max(hv1, hu1)). We can calculate lca in O(log n), using binary lifting, or in O(1), using .

Using the formula we can easy calculate answer for fixed sf and t. To answer the query, we consider all possible permutations of aband c, there are only 3!.

Final asymptotics is O(n · log n + q · log n) or O(n + q), depending on the lca search algorithm.



#include <bits/stdc++.h>#define ll long longusing namespace std;const int maxn=1e5+10;const int DEG=20;const int mod=1e9+7;const ll inf=1e17;int n,q;struct node{    int to,nxt;}edge[maxn*2];int head[maxn],cnt=0;void addedge(int u,int v){    edge[cnt].to=v;    edge[cnt].nxt=head[u];    head[u]=cnt++;}int fa[maxn][DEG];int deg[maxn],vis[maxn];void bfs(int root){    queue<int>que;    deg[root]=0;    fa[root][0]=root;    que.push(root);    while(!que.empty()){        int tmp=que.front();        que.pop();        for(int i=1;i<DEG;++i)            fa[tmp][i]=fa[fa[tmp][i-1]][i-1];        for(int i=head[tmp];i!=-1;i=edge[i].nxt){            int v=edge[i].to;            if(v==fa[tmp][0]) continue;            deg[v]=deg[tmp]+1;            fa[v][0]=tmp;            que.push(v);        }    }}int LCA(int u,int v){    if(deg[u]>deg[v]) swap(u,v);    int hu=deg[u],hv=deg[v];    int tu=u,tv=v;    for(int det=hv-hu,i=0;det;det>>=1,i++)        if(det&1)            tv=fa[tv][i];    if(tu==tv) return tu;    for(int i=DEG-1;i>=0;--i){        if(fa[tu][i]==fa[tv][i]) continue;        tu=fa[tu][i];        tv=fa[tv][i];    }    return fa[tu][0];}int dis(int u,int v){    return deg[u]+deg[v]-2*deg[LCA(u,v)];}int main(){    int x;    memset(head,-1,sizeof(head));    scanf("%d %d",&n,&q);    for(int i=2;i<=n;++i){        scanf("%d",&x);        addedge(i,x);        addedge(x,i);        vis[i]++;        vis[x]++;    }    int root;    for(int i=1;i<=n;++i)        if(vis[i]==1){            root=i;            break;        }    bfs(root);    int a,b,c;    while(q--){        scanf("%d %d %d",&a,&b,&c);        int r1=LCA(a,b);        int r2=LCA(b,c);        int r3=LCA(a,c);        if(deg[r2]>deg[r1]) r1=r2;        if(deg[r3]>deg[r1]) r1=r3;        int ans=max(dis(r1,a),max(dis(r1,b),dis(r1,c)));        printf("%d\n",ans+1);    }    return 0;}


阅读全文
0 0
原创粉丝点击