1. 程式人生 > 實用技巧 >GYM102769K Kingdoms' Power(樹形DP+回溯)

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(); } }