EndSaH @ 2019-01-06 13:09:33
对于这样的一张图:
以第一篇题解为例:
void solve(int u)
{
//judge[i]表示到根距离为i的路径是否存在
vis[u]=judge[0]=1; calc(u);//处理以u为根的子树
for(int i=head[u];i;i=E[i].nxt)//对每个子树进行分治
{
int v=E[i].v;
if(vis[v])continue;
sum=size[v]; maxp[rt=0]=inf;
getrt(v,0); solve(rt);//在子树中找重心并递归处理
}
}
maxp[rt]=sum=n;//第一次先找整棵树的重心
getrt(1,0);
solve(rt);//对树进行点分治
getrt(1,0)
中, 可以求出重心为2
号结点.
但是在solve
函数前面的计算执行完之后的过程中:
sum = size[v]; maxp[rt = 0] = inf;
getrt(v, 0); solve(rt);
若v
为1, 因为一开始getrt(1, 0)
相当于算出以1
为根时各个节点的size
, 那么此时的size[v]
仍为13.
这与点分治的思路并不相符(此时正确的size[1]
应当为以2
为根时的size
, 即6), 很有可能导致接下来递归求重心的过程中出现错误.
但是我看很多题解都是这么打的, 请问一下dalao们, 这样做的缘由是什么?
(如果要打我的脸的话请轻一点emm)
by Binary_Search_Tree @ 2019-08-21 11:41:31
@Holy_Push 我好像这么写被卡过一次qwq
by MagicDuck @ 2019-08-21 11:46:10
有谁会加强数据吗??? 建议卡掉
by Zcus @ 2019-08-21 18:49:17
@EndSaH 你好啊海波
by EndSaH @ 2019-08-21 21:26:24
@Ender_zzm 你好
看下内容
by Zcus @ 2019-08-21 21:52:03
@EndSaH 你说的好像是对的, 但这种情况好像很难被卡因为Sum错了的话v子树内的SizeMax都会有deltaSum的改变, 重心的位置改变量并不会很大吧
by EndSaH @ 2019-08-23 14:04:46
OI Wiki 上提到了这一点:
请注意在重新选择根节点之后一定要重新计算子树的大小,否则一点看似微小的改动就可能会使时间复杂度错误或正确性难以保证。
这边题解区貌似还没有更正这一点,大家可以去参考一下那边的代码。
by YellowBean_Elsa @ 2020-03-11 20:36:02
第一篇题解肯定对的,每次都重新算的