C C++最全【算法基础】 树形DP AcWing 285,2024年最新2024最新C C++面试真题解析

img
img

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

}

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]); // 不选u 则可以选或者不选 取最优解即可
f[u][1] += f[j][0]; // 选u 则他的子节点都不选
}
}

void solve () {
scanf(“%d”, &n);
for(int i = 1; i <= n; i ++) {
scanf(“%d”, &happy[i]);
}
memset(h, -1, sizeof h);
for(int i = 0; i < n - 1; i ++) {
int a, b;
scanf(“%d%d”, &a, &b);
has_father[a] = true; // 说明a 有直接上司
add(b, a);
}
int root = 1; // 统计根节点个数
while(has_father[root]) {
root ++;
}
dfs(root);
printf(“%d\n”, max(f[root][0], f[root][1]));
}

int main(void){
// freopen(“in.txt”,“r”,stdin);
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
int T = 1;
// cin >> T;
while(T --) solve();
return 0;
}


## AcWing 1220. 生命之树


![在这里插入图片描述](https://img-blog.csdnimg.cn/721edaba3655439385d77f2586be16ea.png)



#include
#include
#include
#include <limits.h>
#include
#include
#include
#include
using namespace std;
typedef long long ll;
typedef double db;
typedef pair<int, int> PII;
#define rep(i, a, n) for(int i = a; i <= n; i ++)
#define per(i, a, n) for(int i = n; i <= a; i --)
#define pb push_back
#include <stdlib.h> // atoi
#define debug cout<<“debug”<<“\n”
#define endl “\n”
const int INF = 0x3f3f3f3f;
const int mod=1e9+7;
const int N = 100010;
const int M = N * 2;
#define x first
#define y second

// 上帝要在这棵树内选出一个非空节点集 S,使得对于 S 中的任意两个点 a,b,都存在一个点列 {a,v1,v2,…,vk,b} 使得这个点列中的每个点都是 S 里面的元素,且序列中相邻两个点间有一条边相连。
// 在这个前提下,上帝要使得 S 中的点所对应的整数的和尽量大。 === 实则就是求连通块的max

int n;
int w[N];
int h[N], ne[M], e[M], idx;
ll f[N];

void add(int a, int b) {
e[idx] = b, ne[idx] = h[a], h[a] = idx ++;
}

void 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) {
dfs(j, u);
f[u] += max(0ll, f[j]); // long long的0,和0比较一下,如果<=0没必要加上
}
}
}

void solve () {
cin >> n;
memset(h, -1, sizeof h);
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); // 跟节点没有父节点 所以第二个参数为 -1
ll res = f[1];
for(int i = 1; i <= n; i ++) res = max(res, f[i]);
cout << res << endl;
}

int main(void){
// freopen(“in.txt”,“r”,stdin);

img
img

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

bbs.youkuaiyun.com/topics/618668825)**

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值