题目描述
输入
输出
样例输入
7
6 2
3 4
2 3
1 2
7 6
5 6
样例输出
4
分析:
树上DP。
dp[i][0]表示不选i,以i为根的子树的最大答案。
dp[i][1]表示选i,以i为根的子树的最大答案。
状态转移方程:dp[i][0]=∑max(dp[j][0],dp[j][1]),dp[i][1]=1+∑f[dp][0]
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <iostream> #include <string> #include <cstdio> #include <cmath> #include <cstring> #include <algorithm> #include <vector> #include <queue> #include <deque> #include <map> #define range(i,a,b) for(int i=a;i<=b;++i) #define LL long long #define rerange(i,a,b) for(int i=a;i>=b;--i) #define fill(arr,tmp) memset(arr,tmp,sizeof(arr)) using namespace std; pair<int,int>e[150005]; int tol,h[50005],dp[50005][2],n; void add_edge(int x,int y){ e[++tol].first=y; e[tol].second=h[x]; h[x]=tol; } void init() { cin>>n; range(i,1,n-1){ int x,y; cin>>x>>y; add_edge(x,y); add_edge(y,x); } } void dfs(int x,int fu){ dp[x][1]=1,dp[x][0]=0; for(int i=h[x];i;i=e[i].second){ int fir=e[i].first; if(fir==fu)continue; dfs(fir,x); dp[x][1]+=dp[fir][0]; dp[x][0]+=max(dp[fir][1],dp[fir][0]); } } void solve(){ dfs(1,0); cout<<max(dp[1][0],dp[1][1])<<endl; } int main() { init(); solve(); return 0; }