核心思想
- dfs1.假设一个点为根,并以此求出问题的答案
- dfs2.找到换根后答案的变化规律再做一次dp
E.g1:
来源:【POI2008-BZOJ1131】Sta
题意:给出一个N个点的树,找出一个点来,以这个点为根的树时,所有点的深度之和最大
链接:https://www.luogu.com.cn/problem/P3478
- 题解:
第一次DFS以1为根求出树的深度之和
注意到:根由父节点x向子节点y变,以y为根的子树深度-1,其余节点+1,以此有:f[v]=f[x]+siz[1]-2*siz[v]; - 代码
#include <iostream>
#include <cstdio>
#define maxn 1000005
using namespace std;
int head[maxn],cnt,dep[maxn],siz[maxn],n;
long long f[maxn];
struct fdfdfd{int next,to;}e[maxn<<1];
void addedge(int x,int y){e[++cnt].to=y; e[cnt].next=head[x]; head[x]=cnt;}
void dfs(int x,int pre,int d)
{
dep[x]=d; siz[x]=1;
for(int i=head[x];i;i=e[i].next)
{
int v=e[i].to;
if(v==pre) continue;
dfs(v,x,d+1); dep[x]+=dep[v]; siz[x]+=siz[v];
}
}
void dp(int x,int pre)
{
for(int i=head[x];i;i=e[i].next)
{
int v=e[i].to;
if(v==pre) continue;
f[v]=f[x]+siz[1]-2*siz[v];
dp(v,x);
}
}
int main()
{
scanf("%d",&n);
for(int i=1,u,v;i<n;++i) scanf("%d%d",&u,&v),addedge(u,v),addedge(v,u);
dfs(1,0,1); dp(1,0);
int k=1;
for(int i=2;i<=n;++i)
if(f[k]<f[i]) k=i;
printf("%d
",k);
return 0;
}
E.g2:
来源:CF1092F Tree with Maximum Cost
链接:https://www.luogu.com.cn/problem/CF1092F
题解:https://www.luogu.com.cn/problem/solution/CF1092F
- 代码
#include <iostream>
#include <cstdio>
#define maxn 200005
using namespace std;
int head[maxn],cnt,dep[maxn],a[maxn];
long long suma[maxn],f[maxn];
struct fdfdfd{int next,to;}e[maxn<<1];
void addedge(int x,int y){e[++cnt].to=y; e[cnt].next=head[x]; head[x]=cnt;}
void dfs(int x,int pre,int d)
{
dep[x]=d; suma[x]=a[x];
for(int i=head[x];i;i=e[i].next)
{
int v=e[i].to;
if(v==pre) continue;
dfs(v,x,d+1); suma[x]+=suma[v];
}
}
void dp(int x,int pre)
{
for(int i=head[x];i;i=e[i].next)
{
int v=e[i].to;
if(v==pre) continue;
f[v]=f[x]+suma[1]-2*suma[v];
dp(v,x);
}
}
int main()
{
int n; scanf("%d",&n);
for(int i=1;i<=n;++i) scanf("%d",&a[i]);
for(int i=1,u,v;i<n;++i) scanf("%d%d",&u,&v),addedge(u,v),addedge(v,u);
dfs(1,0,0);
for(int i=1;i<=n;++i) f[1]+=1ll*a[i]*dep[i];//初始化 以1为根时问题的答案
dp(1,0);
int k=1;
for(int i=2;i<=n;++i)
if(f[k]<f[i]) k=i;
printf("%lld
",f[k]);
return 0;
}
比较套路,树形DP的一个小分支