动态规划刷题

发布于:2025-02-14 ⋅ 阅读:(123) ⋅ 点赞:(0)

P1122最大子树和

通过链式前向星建树,然后通过遍历每一个点作为根节点然后进行剪枝,通过dfs找子树f[i]<0的就减去。

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
int n;
const int N=160010;
int a[N];
int h[N],e[N],ne[N],idx;
int res=-2147483647;
int f[N];
void add(int a,int b){
	e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
void dfs(int u,int fa){
	for(int i=h[u];i!=-1;i=ne[i]){
		int j=e[i];
		if(j!=fa){
			dfs(j,u);
			if(f[j]>0)f[u]+=f[j];
		}
	}
}
int main(){
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>a[i];
		f[i]=a[i];
	}
	memset(h,-1,sizeof(h));
	for(int i=1;i<n;i++){
		int a,b;cin>>a>>b;
		add(a,b),add(b,a);
	}
	dfs(1,0);
	for(int i=1;i<=n;i++)res=max(res,f[i]);
	cout<<res<<endl;
	return 0;
} 

洛谷P1352没有上司的舞会

通过链式前向星建树,然后记录建树时的父节点has_father[]变成true,通过while遍历has_father数组进行找根,通过dfs进行根节点遍历,然后分有没有包括根节点自身f[u][1]和f[u][0]进行分类状态转移,最后输出两个的最大值。

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
int n;
const int N=6010;
int happy[N];
int f[N][2];
int h[N],e[N],ne[N],idx;
bool has_father[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][1]+=f[j][0];
		f[u][0]+=max(f[j][0],f[j][1]);
	}
}
int main(){
	cin>>n;
	for(int i=1;i<=n;i++)cin>>happy[i];
	memset(h,-1,sizeof(h));
	for(int i=1;i<n;i++){
		int a,b;cin>>a>>b;
		has_father[a]=true;
		add(b,a);
	}
	int root=1;
	while(has_father[root])root++;
	dfs(root);
	cout<<max(f[root][0],f[root][1])<<endl;
	
	return 0;
} 


网站公告

今日签到

点亮在社区的每一天
去签到