树形DP2

作业介绍

#include <bits/stdc++.h>
using namespace std;
const int N = 6e3+5;
int n,a[N],f[N][2];
vector<int>e[N];
void dfs(int x,int fa){
	f[x][1] = a[x];
	for(auto v:e[x]){
		if(v==fa)continue;
		dfs(v,x);
		f[x][0]+=max(f[v][0],f[v][1]);
		f[x][1]+=f[v][0];
	}
}
int main(){
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>a[i];
	}
	for(int i=1;i<n;i++){
		int x,y;
		cin>>x>>y;
		e[x].push_back(y);
		e[y].push_back(x);
	}
	dfs(1,0);
	cout<<max(f[1][0],f[1][1])<<endl;
	return 0;
}
/*
f[x][0]管x及x的子树和x的父亲的最小花费
f[x][1]管x及x的子树的最小花费
f[x][2]管x的子树的最小花费
f[x][0] = 1+sigma(f[v][2])
f[x][1] = min(f[v][0]+sigma(f[t][1])
f[x][2] = sigma(f[v][1])
*/
#include <bits/stdc++.h>
using namespace std;
const int N = 10005;
int n,f[N][4];
vector<int>e[N];
void dfs(int x,int fa){
	f[x][0] = 1;
	int sum = 0;
	for(auto v:e[x]){
		if(v==fa)continue;
		dfs(v,x);
		sum+=f[v][1];
		f[x][0]+=f[v][2];
		f[x][2]+=f[v][1];
	}
	f[x][1] = 1e9;
	for(auto v:e[x]){
		if(v==fa)continue;
		f[x][1] = min(f[x][1],f[v][0]+sum-f[v][1]);
	}
	for(int i=1;i<=2;i++){
		f[x][i] = min(f[x][i],f[x][i-1]);
	}
}
int main(){
	cin>>n;
	for(int i=1;i<n;i++){
		int x,y;
		cin>>x>>y;
		e[x].push_back(y);
		e[y].push_back(x);
	}
	dfs(1,0);
	cout<<f[1][1]<<endl;
	return 0;
}
/*
f[x][0]管x及x的子树和x的父亲的最小花费
f[x][1]管x及x的子树的最小花费
f[x][2]管x的子树的最小花费
f[x][0] = 1+sigma(f[v][2])
f[x][1] = min(f[v][0]+sigma(f[t][1])
f[x][2] = sigma(f[v][1])
*/
#include <bits/stdc++.h>
using namespace std;
const int N = 10005;
int n,f[N][4],a[N];
vector<int>e[N];
void dfs(int x,int fa){
	f[x][0] = a[x];
	int sum = 0;
	for(auto v:e[x]){
		if(v==fa)continue;
		dfs(v,x);
		sum+=f[v][1];
		f[x][0]+=f[v][2];
		f[x][2]+=f[v][1];
	}
	f[x][1] = 1e9;
	for(auto v:e[x]){
		if(v==fa)continue;
		f[x][1] = min(f[x][1],f[v][0]+sum-f[v][1]);
	}
	for(int i=1;i<=2;i++){
		f[x][i] = min(f[x][i],f[x][i-1]);
	}
}
int main(){
	cin>>n;
	for(int i=1;i<=n;i++){
		int x,t,m;
		cin>>x>>t>>m;
		a[x] = t;
		for(int j=1;j<=m;j++){
			int y;
			cin>>y;
			e[x].push_back(y);
			e[y].push_back(x);
		}
	}
	dfs(1,0);
	cout<<f[1][1]<<endl;
	return 0;
}
/*
f[x][0]管x、x的子树、父亲、爷爷的最小花费
f[x][1]管x、x的子树、父亲的最小花费
f[x][2]管x、x的子树的最小花费
f[x][3]管x的子树的最小花费
f[x][4]管x的子树的子树

f[x][0] = 1+sigma(f[v][4])
f[x][1] = f[v][0] + sigma(f[t][3])
f[x][2] = f[v][1] + sigma(f[t][2])
f[x][3] = sigma(f[v][2])
f[x][4] = sigma(f[v][3])
*/
#include <bits/stdc++.h>
using namespace std;
const int N = 1005;
int n,f[N][5];
vector<int>e[N];
void dfs(int x,int fa){
	f[x][0] = 1;
	int sum2=0,sum3=0;
	for(auto v:e[x]){
		if(v==fa)continue;
		dfs(v,x);
		f[x][0]+=f[v][4];
		f[x][3]+=f[v][2];
		f[x][4]+=f[v][3];
		sum2+=f[v][2];
		sum3+=f[v][3];
	}
	f[x][1] = f[x][2] = 1e9;
	for(auto v:e[x]){
		if(v==fa)continue;
		f[x][1] = min(f[x][1],f[v][0]+sum3-f[v][3]);
		f[x][2] = min(f[x][2],f[v][1]+sum2-f[v][2]);
	}
	for(int i=1;i<=4;i++){
		f[x][i] = min(f[x][i],f[x][i-1]);
	}
}
int main(){
	cin>>n;
	for(int i=2;i<=n;i++){
		int x,y;
		cin>>x;
		e[i].push_back(x);
		e[x].push_back(i);
	}
	dfs(1,0);
	cout<<f[1][2]<<endl;
	return 0;
}
/*
f[x][i]x的子树通过最多i条边能到的点
f[x][i] = sigma(f[v][i-1])

g[x][i]x的子树外最多i条边能到x的点
g[x][i] = g[fa][i-1]+(f[fa][i-1]-f[x][i-1])
*/
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5+5;
int n,f[N][25],a[N],g[N][25],k;
vector<int>e[N];
void dfs1(int x,int fa){
	f[x][0] = a[x];
	for(auto v:e[x]){
		if(v==fa)continue;
		dfs1(v,x);
		for(int i=1;i<=k;i++){
			f[x][i] += f[v][i-1];	
		}
	}

}
void dfs2(int x,int fa){
	if(x!=1){
		for(int i=1;i<=k;i++){
			g[x][i] += g[fa][i-1];
			g[x][i]+=f[fa][i-1]-f[x][i-2];
		}	
	}
	for(auto v:e[x]){
		if(v==fa)continue;
		dfs2(v,x);
	}

}
int main(){
	cin>>n>>k;
	for(int i=1;i<n;i++){
		int x,y;
		cin>>x>>y;
		e[x].push_back(y);
		e[y].push_back(x);
	}
	for(int i=1;i<=n;i++){
		cin>>a[i];
	}
	dfs1(1,0);
	for(int x=1;x<=n;x++){
		for(int i=1;i<=k;i++){
			f[x][i]+=f[x][i-1];
		}
	}
	
	dfs2(1,0);
	for(int i=1;i<=n;i++){
	//	cout<<f[i][k]<<" "<<g[i][k]<<endl;
		cout<<f[i][k]+g[i][k]<<endl;
	}
	return 0;
}

题目

认领作业后才可以查看作业内容。
状态
正在进行…
题目
9
开始时间
2026-4-11 0:00
截止时间
2026-4-19 23:59
可延期
24 小时