【 Codeforces Round #425 (Div. 2) D】Misha, Grisha and Underground

Link:http://codeforces.com/contest/832/problem/D

Description

给你一棵树;
然后给你3个点
让你把这3个点和点s,t,f对应;
然后s先从s走到f;
之后t再从t走到f;
求这两条路径的公共路径的长度;

Solution

答案为
dis(s,f)+dis(t,f)dis(s,t)2
树上最短路径做一下就好;
LCA!

NumberOf WA

0

Reviw

想得太慢了

Code

#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>

using namespace std;

const int MAXN = 100000+5;
const int MAX = 17;

vector <int> son[MAXN],w[MAXN];
int n,p[MAXN][MAX+5],dep[MAXN],pre[MAX+5],m,t[3];
long long dis[MAXN];

void input(int &r)
{
    char t = getchar();
    while (!isdigit(t)) t = getchar();
    r = 0;
    while (isdigit(t)) r = r * 10 + t - '0', t = getchar();
}

void dfs(int x,int f)
{
    dep[x] = dep[f] + 1;
    p[x][0] = f;
    for (int i = 1; i <= MAX; i++)
        p[x][i] = p[p[x][i - 1]][i - 1];
    int len = son[x].size();
    for (int i = 0; i <= len - 1; i++)
    {
        int y = son[x][i];
        if (y != f)
        {
            dis[y] = dis[x] + w[x][i];
            dfs(y, x);
        }
    }
}

int midis(int t0,int t1){
    int pret0,pret1;
    pret0 = t0; pret1 = t1;
    if (dep[t0] > dep[t1])
        swap(t0, t1);
    for (int i = MAX; i >= 0; i--)
        if (dep[t0] <= dep[t1] - pre[i])
            t1 = p[t1][i];
    if (t1 == t0)
    {
        return dis[pret0]+dis[pret1]-2*dis[t0];
    }
    for (int i = MAX; i >= 0; i--)
    {
        if (p[t0][i] == p[t1][i])
            continue;
        t0 = p[t0][i], t1 = p[t1][i];
    }
    return dis[pret0]+dis[pret1]-2*dis[p[t0][0]];
}

int get_ans(){
    int temp1 = 0;
    for (int S = 0;S <= 2;S++)
        for (int T = 0;T <= 2;T++)
            if (S!=T)
                for (int F = 0;F <= 2;F++)
                    if (S!=F && T!=F){
                        int temp = midis(t[S],t[F]);
                        temp+=midis(t[T],t[F]);
                        temp-=midis(t[S],t[T]);
                        temp/=2;
                        temp1 = max(temp1,temp);
                    }
    return temp1;
}

int main()
{
    //freopen("F:\\rush.txt", "r", stdin);
    pre[0] = 1;
    for (int i = 1; i <= MAX; i++)
        pre[i] = pre[i - 1] << 1;
    input(n); input(m);
    for (int i = 2; i <= n; i++)
    {
        int x;
        input(x);
        son[x].push_back(i);
        w[x].push_back(1);
    }
    dis[1] = 0;
    dfs(1, 0);
    for (int i = 1; i <= m; i++)
    {
        int t0, t1,t2,pret0,pret1;
        for (int j = 0;j <= 2;j++)
            input(t[j]);
        printf("%d\n",get_ans()+1);
    }
    return 0;
}
posted @ 2017-10-04 18:44  AWCXV  阅读(154)  评论(0编辑  收藏  举报