树形DP模型
285. 没有上司的舞会
https://www.acwing.com/problem/content/287/

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<vector>
#include<queue>
#include<stack>
#include<cstring>
#include<unordered_map>
using namespace std;
typedef long long LL;
const int N=6010;
int f[N][2];//f(i,0) 不选择i f(i,1)选择i
int happy[N];
int h[N],e[N],ne[N],idx;
bool is_children[N];
int n;
void add(int a,int b){
e[idx]=b;
ne[idx]=h[a];
h[a]=idx++;
}
void dfs(int u){
f[u][1]=happy[u];
for(int i=h[u];i!=-1;i=ne[i]){
int j=e[i];
dfs(j);
f[u][0]+=max(f[j][0],f[j][1]);
f[u][1]+=f[j][0];
}
}
int main(){
memset(h,-1,sizeof h);
cin>>n;
for(int i=1;i<=n;i++) cin>>happy[i];
for(int i=1;i<n;i++){
int a,b;
cin>>a>>b;
add(b,a);
is_children[a]=true;
}
int root=1;
while(is_children[root]) root++;
dfs(root);
cout<<max(f[root][0],f[root][1])<<endl;
return 0;
}
// freopen("testdata.in", "r", stdin);
1072. 树的最长路径
https://www.acwing.com/problem/content/1074/
树的直径写法
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<vector>
#include<queue>
#include<stack>
#include<cstring>
#include<unordered_map>
using namespace std;
typedef long long LL;
const int N=2e5+10;
int h[N],w[N],ne[N],e[N],idx;
int dist[N];
int n;
void add(int a,int b,int c){
e[idx]=b;
w[idx]=c;
ne[idx]=h[a];
h[a]=idx++;
}
void dfs(int u,int father,int distance){
dist[u]=distance;
for(int i=h[u];i!=-1;i=ne[i]){
int j=e[i];
if(j!=father){
dfs(j,u,distance+w[i]);
}
}
}
int main(){
cin>>n;
memset(h,-1,sizeof h);
for(int i=0;i<n-1;i++){
int a,b,c;
cin>>a>>b>>c;
add(a,b,c);
add(b,a,c);
}
dfs(1,-1,0);
int u=1;
for(int i=1;i<=n;i++){
if(dist[i]>dist[u]) u=i;
}
dfs(u,-1,0);
for(int i=1;i<=n;i++){
if(dist[i]>dist[u]) u=i;
}
int s=dist[u];
cout<<s<<endl;
return 0;
}
// freopen("testdata.in", "r", stdin);
树形DP写法
树形dp,实际上就是两次dfs,
从一个点出发找一条最长边,和一条次长边
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<vector>
#include<queue>
#include<stack>
#include<cstring>
#include<unordered_map>
using namespace std;
typedef long long LL;
const int N=2e5+10;
int h[N],w[N],e[N],ne[N],idx;
void add(int a,int b,int c){
e[idx]=b;
w[idx]=c;
ne[idx]=h[a];
h[a]=idx++;
}
int ans=0;
int n;
int dfs(int u,int father){
int dist=0;//表示从u出发向下走的最大长度
int d1=0;//最大长度
int d2=0;//次大长度
for(int i=h[u];i!=-1;i=ne[i]){
int j=e[i];
if(j==father) continue;
int d=dfs(j,u)+w[i];
dist=max(dist,d);
if(d>=d1){
d2=d1;
d1=d;
}
else if(d>d2){
d2=d;
}
ans=max(ans,d1+d2);
}
return dist;
}
int main(){
cin>>n;
memset(h,-1,sizeof h);
for(int i=0;i<n-1;i++){
int a,b,c;
cin>>a>>b>>c;
add(a,b,c);
add(b,a,c);
}
dfs(1,-1);
cout<<ans<<endl;
return 0;
}
// freopen("testdata.in", "r", stdin);
1073. 树的中心
https://www.acwing.com/problem/content/description/1075/

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<vector>
#include<queue>
#include<stack>
#include<cstring>
#include<unordered_map>
using namespace std;
typedef long long LL;
const int N=2e5+10,INF=0x3f3f3f3f;
int h[N],ne[N],e[N],w[N],idx;
int n;
int d1[N],d2[N],up[N],p1[N];
bool is_leaf[N];
void add(int a,int b,int c){
e[idx]=b;
w[idx]=c;
ne[idx]=h[a];
h[a]=idx++;
}
int dfsdown(int u,int father){
d1[u]=d2[u]=-INF;
for(int i=h[u];i!=-1;i=ne[i]){
int j=e[i];
if(j==father) continue;
int d=dfsdown(j,u)+w[i];
if(d>=d1[u]){
d2[u]=d1[u];
d1[u]=d;
p1[u]=j;//进行保存,表面u-j是从u走的最大路径
}
else if(d>d2[u]) d2[u]=d;
}
if(d1[u]==-INF){
d1[u]=d2[u]=0;
//说明无法向下走 是叶子
is_leaf[u]=true;
}
return d1[u];
}
void dfsup(int u,int father){
for(int i=h[u];i!=-1;i=ne[i]){
int j=e[i];
if(j==father) continue;
if(p1[u]==j){//说明u-j就是最大路径,所以必须选择次大路径才能避免重复走
up[j]=max(up[u],d2[u])+w[i];
}
else up[j]=max(up[u],d1[u])+w[i];
dfsup(j,u);
}
}
int main(){
cin>>n;
memset(h,-1,sizeof h);
for(int i=0;i<n-1;i++){
int a,b,c;
cin>>a>>b>>c;
add(a,b,c);
add(b,a,c);
}
dfsdown(1,-1);
dfsup(1,-1);
int res=d1[1];
for (int i = 2; i <= n; i ++ )
if (is_leaf[i]) res = min(res, up[i]);
else res = min(res, max(d1[i], up[i]));
printf("%d\n", res);
return 0;
}
// freopen("testdata.in", "r", stdin);
1075. 数字转换
https://www.acwing.com/problem/content/description/1077/
一:求2 到 n 中每一个数的因数和,1不算是因为题意
for(int i = 1;i <= n;++i)//i是因数
for(int j = 2;j <= n/i;++j)//j代表i的放大倍数
sum[i*j] += i;

#include <bits/stdc++.h>
using namespace std;
const int N = 50010, M = N * 2;
int h[N], w[M], ne[M], v[M], idx;
int sum[N];
int n;
int ans;
void add(int a, int b, int c){
++idx;w[idx] = c;v[idx] = b;ne[idx] = h[a];h[a] = idx;
}
int dfs(int u){
int d1 = 0, d2 = 0;
for(int i = h[u];i;i = ne[i]){
int k = v[i];
int d = dfs(k) + w[i];
if(d >= d1) d2 = d1, d1 = d;
else if(d > d2) d2 = d;
}
ans = max(ans, d1 + d2);
return d1;
}
int main(){
cin >> n;
for(int i = 1;i <= n;++i)
for(int j = 2;j <= n/i;++j)
sum[i*j] += i;
for(int i = 2;i <= n;++i)
if(sum[i] < i)
add(sum[i], i, 1);
dfs(1);
cout << ans << endl;
return 0;
}
1220. 生命之树
https://www.acwing.com/problem/content/1222/
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<vector>
#include<queue>
#include<stack>
#include<cstring>
#include<unordered_map>
using namespace std;
typedef long long LL;
const int N=2e6+10;
int h[N],e[N],ne[N],w[N],idx;
int n;
LL f[N];
void add(int a,int b){
e[idx]=b;
ne[idx]=h[a];
h[a]=idx++;
}
LL dfs(int u,int father){
f[u]=w[u];
for(int i=h[u];i!=-1;i=ne[i]){
int j=e[i];
if(j==father) continue;
f[u]=max(f[u],f[u]+dfs(j,u));
}
return f[u];
}
int main(){
memset(h,-1,sizeof h);
cin>>n;
for(int i=1;i<=n;i++) cin>>w[i];
for(int i=0;i<n-1;i++){
int a,b;
cin>>a>>b;
add(a,b);
add(b,a);
}
dfs(1,-1);
LL res=f[1];
for(int i=2;i<=n;i++){
res=max(res,f[i]);
}
cout<<res<<endl;
return 0;
}
// freopen("testdata.in", "r", stdin);
1078. 旅游规划
https://www.acwing.com/problem/content/1080/
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<vector>
#include<queue>
#include<stack>
#include<cstring>
#include<unordered_map>
using namespace std;
typedef long long LL;
const int N=2e5+10,M=2*N;
int h[N],e[M],ne[M],idx;
int d1[N],d2[N],up[N],p[N];
int n,len=0;
void add(int a,int b){
e[idx]=b;
ne[idx]=h[a];
h[a]=idx++;
}
void dfs_down(int u,int father){
for(int i=h[u];i!=-1;i=ne[i]){
int j=e[i];
if(j==father) continue;
dfs_down(j,u);
int d=d1[j]+1;
if(d>=d1[u]){
p[u]=j;
d2[u]=d1[u];
d1[u]=d;
}
else if(d>d2[u]){
d2[u]=d;
}
}
len=max(len,d1[u]+d2[u]);
}
void dfs_up(int u,int father){
for(int i=h[u];i!=-1;i=ne[i]){
int j=e[i];
if(j==father) continue;
up[j] = up[u] + 1;//算出从j到u继续往上走的值
if(p[u]==j) up[j]=max(up[j],1+d2[u]);//和往下走的值进行比较
else up[j]=max(up[j],1+d1[u]);
dfs_up(j,u);
}
}
int main(){
cin>>n;
memset(h,-1,sizeof h);
for (int i = 0; i < n-1; i ++ ){
int a,b;
cin>>a>>b;
add(a,b);
add(b,a);
}
dfs_down(0,-1);
dfs_up(0,-1);
for (int i = 0; i < n; i ++ )
{
int d[3] = {d1[i], d2[i], up[i]};
sort(d, d + 3);
if (d[1] + d[2] == len) printf("%d\n", i);
}
return 0;
}
// freopen("testdata.in", "r", stdin);

浙公网安备 33010602011771号