分析
我A紫题了耶
这题乍一看好像不难啊就一个树形DP啊最多加上LCA处理一下啊。。。想来想去不太行。
feelings:有一点是确定的,就是我们要让军队尽量离根节点近一点,这样子就可以让这个军队控制的节点更多。而答案就是用时最大的那个军队的时间,而我们要让这个最大值最小,所以可能是二分答案。
这题思路线比较长,从这两个点入手,大致分几个步骤,我一个一个写出。
1、倍增预处理关系和距离
“让军队向上移动”的“上提”操作,就很容易想到用倍增优化。
设 f [ i ] [ j ] f[i][j] f[i][j] 为 i i i 往上 2 j 2^j 2j 个节点,容易知道 f [ i ] [ 0 ] f[i][0] f[i][0] 就是 i i i 的父亲。设 d i s [ i ] [ j ] dis[i][j] dis[i][j] 为 i i i 到 i i i 往上 2 j 2^j 2j 个节点的距离。由类似求LCA前的预处理那样子,递推式显然,用个DFS遍历很容易求出。不会的先去学倍增LCA先。
void dfs(int x,int fx,int d)//倍增预处理
{
f[x][0]=fx;
dis[x][0]=d;
for(int i=1;i<=16;i++)
{
f[x][i]=f[f[x][i-1]][i-1];
dis[x][i]=dis[x][i-1]+dis[f[x][i-1]][i-1];
}
for(int i=hd[x];i;i=e[i].next)
{
if(e[i].to!=fx) dfs(e[i].to,x,e[i].w);
}
}
2、二分答案
直接二分一个时间,作为本次每支军队移动的最大时间,判断行不行,然后再次二分。这一部分很简单。
int l=1,r=1000000;
while(l<=r)
{
int mid=(l+r)>>1;
if(pd(mid))
{
fff=1;//有解标记
ans=mid;
r=mid-1;