CF 379F: New Year Tree

题目链接:

http://codeforces.com/contest/379/problem/F


题目大意:

给定一棵树,

每次向树上的某个节点添加两个子节点,然后询问树的直径(树上最长路径)。


算法:

如果我们记录下添加节点前树上的最远路径长度及两个端点A,B。

那么添加两个新节点之后,距离这个点最远的那个点,肯定是原直径的两个端点之一。

所以只要计算dis(新节点1,A)和dis(新节点2,B),如果比原答案大的话,就更新答案和A、B的值。

于是就变成了一道LCA模板题,求LCA的时候顺便求出两点距离也是很简单的事情 。


PS:

谢谢wuyiqi大神和sjb大神给我讲了一些这道题需要的性质

推荐一篇关于树的直径的文章


代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>

const int MAXN = 1100000;
const int MAXD = 20;
int go[MAXN][MAXD], dep[MAXN];
std::vector <int> mm[MAXN];

void dfs(int u)
{
    for(int i = 0; i < mm[u].size(); i ++)
    {
        if (dep[mm[u][i]] != -1)
        {
            continue;
        }
        int v = mm[u][i];
        dep[v] = dep[u] + 1;
        go[v][0] = u;
        for (int k = 1; (1 << k) <= dep[v]; k ++)
        {
            go[v][k] = go[go[v][k - 1]][k - 1];
        }
        dfs(v);
    }
}

int lca(int u, int v)
{
    if (dep[v] > dep[u])
    {
        std::swap(u,v);
    }
    int jmp = dep[u] - dep[v];
    for (int k = MAXD - 1; k >= 0; k --)
    {
        if(jmp >> k & 1)
        {
            u = go[u][k];
        }
    }
    if (u == v)
    {
        return jmp;
    }
    int tmp = 0;
    for(int k = MAXD - 1; k >= 0; k --)
    {
        if(((1 << k) < dep[u]) && (go[u][k] != go[v][k]))
        {
            u = go[u][k];
            v = go[v][k];
            tmp |= 1 << k;
        }
    }
    tmp ++;
    return jmp + tmp * 2;
}

int main()
{
    int n;
    scanf("%d", &n);
    for(int i = 0; i <  2 * n + 4; i ++)
    {
        mm[i].clear();
    }
    memset(dep, -1, sizeof(dep));
    memset(go, -1, sizeof(go));
    mm[0].push_back(1);
    mm[0].push_back(2);
    mm[0].push_back(3);
    dep[0] = 0;
    dfs(0);
    int node1 = 1, node2 = 2;
    int ans = 2;
    for (int i = 0; i < n; i ++)
    {
        int x;
        scanf("%d",&x);
        x --;
        mm[x].push_back(i * 2 + 4);
        mm[x].push_back(i * 2 + 5);
        dfs(x);
        int tmp;
        if ((tmp = lca(node1, i * 2 + 4)) > ans)
        {
            node2 = i * 2 + 4;
            ans = tmp;
        }
        if ((tmp = lca(node2, i * 2 + 5)) > ans)
        {
            node1 = i * 2 + 5;
            ans = tmp;
        }
        printf("%d\n", ans);
    }
    return 0;
}


你可能感兴趣的:(CF 379F: New Year Tree)