建议去别的地方看一下点分治的具体步骤之后再来看代码
我的代码有详细解释
//每次到子树中找子树重心(即遍历一遍子树)O(n),而共需找log次,因为每次都把树分成了两段 //=>点分治复杂度O(nlogn) struct pp { int next,to,w; }edge[_]; void getroot(rg int i,rg int dad,rg int s)//找重心 //s:该联通块大小 { size[i]=1;//该点子树大小 F[i]=0;//最大儿子子树大小 dfn[i]=++dfns; for(rg int j=record[i];j;j=edge[j].next) { rg int to=edge[j].to; if(to!=dad&&!passed[to])//passed[]数组只标记找过的重心,因为要把树隔开 { getroot(to,i); F[i]=max(F[i],size[to]); size[i]+=size[to]; } } F[i]=max(F[i],s-size[i]);//别忘了该点父亲也算是其儿子,只不过(to!=dad)阻止了遍历回去,在这里用树的总大小(s)减去该点size->求出其父所在子树大小 _ _ root=F[i]<F[root]?i:root;//找到重心,用root这个词是因为不知道重心的英文是什么( v ) } void dfs(rg int i,rg int all) { // FFF : 让火焰净化一切!!! passed[i]=1;//dfs函数是从重心出发的,为了隔开子树,把其标记为走过 for(rg int j=record[root];j;j=edge[j].next) { rg int to=edge[j].to; if(!passed[to]) { rg int s; if(dfn[to]>dfn[i])s=size[to];//初始化!!! else s=all-size[i]; root=0;//初始化!!! dfns=0;//初始化!!! getroot(to,0,s); dfs(root,s); } } } // F[0]=n; !!!!