题解 P7320 【[JSOI2013] 哈利波特与死亡圣器】

· · 题解

分析

先考虑当 i 号节点被攻克时,哪些节点需要修筑好防御。

按照题意,由于下一步伏地魔大军可能前往任何它的子节点,所以,它所有的子节点都要修筑好防御。

然后分析当 i 号节点被攻克时,哪些节点已经修筑好防御。

伏地魔要攻克到 i 节点,需要走 (1,i) 的路径,攻克这一路上所有的节点。按照上面的结论可得:

那么对于 $i$ 节点,对这么多节点修筑好防御有多少时间呢? 不难发现,如果设 $1$ 号节点的深度为 $1$,那么把这些节点修筑好防御的时间恰好是节点 $i$ 的深度。 也就是说,需要找到一个整数 $ans$,使得 $\forall i\leq n$,都满足以上结论。 ## 代码 具体实现看代码,有详细注释: ```cpp #include <bits/stdc++.h> #define pb push_back using namespace std; int n,ans,x,y; vector<int>v[300001]; void dfs(int fa,int x,int sum,int step) {//fa:当前节点的父节点 x:当前节点 //sum:目前节点被攻克时,需要修筑好防御的节点数 step:当前节点深度 sum+=v[x].size()-1;//加上目前节点的子节点 if(x==1) sum++; //如果是根节点,那么所有连边连到的点全部都是子节点,额外加一 ans=max(ans,(int)ceil(sum*1.0/step)); //计算在step小时内修筑sum个节点需要的人数,刷新最大值 for(register int i=v[x].size()-1; i>=0; i--) if(v[x][i]!=fa) dfs(x,v[x][i],sum,step+1); } int main() { cin>>n; for(register int i=1; i<n; i++) cin>>x>>y,v[x].pb(y),v[y].pb(x); dfs(0,1,0,1); cout<<ans<<endl; return 0; } ``` ### 祝大家AC愉快!