GYM102769K Kingdoms' Power(树形DP+回溯)

题意:

有一棵根节点为1的树,根节点处有无限个部队,每次操作你能让一个部队移动一步,问你最少移动多少次可以遍历完这个树。

题解:

非常巧妙的树形DP,跪了

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+100;
int n;
vector<int> g[maxn];
int pre[maxn];
int dep[maxn];
int maxDep[maxn];
long long ans;
void dfs1 (int u,int f) {
    dep[u]=dep[f]+1;
    maxDep[u]=dep[u];
    for (int v:g[u]) {
        if (v!=f) {
            dfs1(v,u);
            maxDep[u]=max(maxDep[u],maxDep[v]);
            //更新距离它最远的叶子节点是多少 
        }
    }
} 

long long dfs2 (int u,int f) {
    pre[u]=u;
    for (int v:g[u]) {
        if (v==f) continue;
        ans+=min(dep[u],dep[pre[u]]-dep[u]+1);
        dfs2(v,u);
        pre[u]=pre[v];
    }
}
bool cmp (int x,int y) {
    return maxDep[x]<maxDep[y];
}
int main () {
    int T;
    scanf("%d",&T);
    for (int k=1;k<=T;k++) {
        int n;
        scanf("%d",&n);
        ans=0;
        for (int i=2;i<=n;i++) {
            int x;
            scanf("%d",&x);
            g[x].push_back(i);
            g[i].push_back(x);
        }
        dfs1(1,0);
        for (int i=1;i<=n;i++) sort(g[i].begin(),g[i].end(),cmp);
        dfs2(1,0);
        printf("Case #%d: %lld\n",k,ans);
        for (int i=1;i<=n;i++) g[i].clear();
    }
}

 

posted @ 2020-10-28 12:34  zlc0405  阅读(98)  评论(0编辑  收藏  举报