思路:
首先这是个在树上用的东西,一般就是不告诉你哪个点作为根,而你就需要求出所有点作为根时的答案,然后才能得到最终的答案。
思路也不是什么很神奇的东西:就是一开始先固定一个点作为根,然后 dp 一次求出解,然后利用这个解再做一次 dp——这次 dp我们称为换根,这次 dp 求出其他点作为根时的解。
举例子: (此例子将会画图分析换根过程)
题意:
求1~n节点分别为根的最小深度和是多少
解析:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e6+10;
int e[N<<1],ne[N<<1],h[N<<1],idx;
int depth[N];
int size[N];
int f[N];
int n,u,v;
int ans;
void add(int a,int b)
{
e[idx]=b;ne[idx]=h[a];h[a]=idx++;
}
void dfs(int u,int fa,int c){
depth[u]=c;size[u]=1;
for(int i=h[u];~i;i=ne[i]){
int v=e[i];
if(v==fa) continue;
dfs(v,u,c+1);
size[u]+=size[v];
depth[u]+=depth[v];
}
}
void dfs1(int u,int fa)
{
for(int i=h[u];~i;i=ne[i]){
int v=e[i];
if(v==fa) continue;
f[v]=f[u]-size[v]+(n-size[v]);
dfs1(v,u);
}
}
int main()
{
memset(h,-1,sizeof h);
scanf("%d",&n);
for(int i=1;i<=n-1;i++){
scanf("%d %d",&u,&v);
add(u,v);add(v,u);
}
ans=0x3f3f3f3f;
dfs(1,0,0);
f[1]=depth[1];
dfs1(1,0);
for(int i=1;i<=n;i++) ans=min(ans,f[i]);
printf("%d\n",ans);
return 0;
}