【题目来源】
https://www.luogu.com.cn/problem/P2996
【题目描述】
经过了几周的辛苦工作,Bessie 终于迎来了一个假期。
作为奶牛群中最会社交的牛,她希望去拜访 N(1≤N≤50000) 个朋友。这些朋友被标号为 1,2,...,N。这些奶牛有一个不同寻常的交通系统,里面有 N−1 条路,每条路连接了一对编号为 C1 和 C2 的奶牛 (1≤C1≤N,1≤C2≤N,C1≠C2 )。这样,在每一对奶牛之间都有一条唯一的通路。
FJ 希望 Bessie 尽快的回到农场。于是,他就指示 Bessie:如果对于一条路直接相连的两个奶牛,Bessie 只能拜访其中的一个。当然,Bessie 希望她的假期越长越好,所以她想知道她可以拜访的奶牛的最大数目。
【输入格式】
第一行,1 个整数 N。
接下来 N−1 行,每行 2 个整数 C1,C2,表示有一条通路连接了编号为 C1 和 C2 的奶牛。
【输出格式】
第一行,1 个整数,代表 Bessie 最多能拜访有多少头奶牛。
【输入样例】
7
6 2
3 4
2 3
1 2
7 6
5 6
【输出样例】
4
【数据范围】
1≤N≤50000
1≤C1≤N,1≤C2≤N,C1≠C2
【算法分析】
● 本题与"洛谷 P1352:没有上司的舞会:https://blog.csdn.net/hnjzsyjyj/article/details/168026658"同模板,且略简单。
● 此题是树形动态规划的经典习题,也是树上最大权独立集简单题。
(1)状态定义
fu0:不选 u 时,以 u 为根的子树最大权。
fu1:选 u 时,以 u 为根的子树最大权。
(2)转移方程(u:当前子树的根节点,v:u 的所有直接子节点,valu:节点 u 的权值)
fu0 = Σ max(fv0, fv1)
fu1 = valu + Σ fv0
【算法代码】
cpp
#include<bits/stdc++.h>
using namespace std;
const int N=5e4+5;
vector<int> g[N];
long long f[N][2];
int n;
void dfs(int u,int fa) {
f[u][0]=0;
f[u][1]=1;
for(int v:g[u]) {
if(v==fa) continue;
dfs(v,u);
f[u][0]+=max(f[v][0],f[v][1]);
f[u][1]+=f[v][0];
}
}
int main() {
cin>>n;
for(int i=1; i<n; i++) {
int u,v;
cin>>u>>v;
g[u].push_back(v);
g[v].push_back(u);
}
dfs(1,0);
cout<<max(f[1][0],f[1][1])<<endl;
return 0;
}
/*
in:
7
6 2
3 4
2 3
1 2
7 6
5 6
out:
4
*/
【参考文献】
https://blog.csdn.net/hnjzsyjyj/article/details/168026658