牛客—— 旅游 (树形DP求树的最大独立集)
题意:
树的最大独立集定义: 对于一棵有N个结点的无根树,选出尽量多的结点,使得任何两个结点均不相邻(称为最大独立集) ;
对于任意一个点x,都有选和不选两种情况。
我们假设dp[x] [0]表示不选该点的最大值,dp[x] [1] 表示选择该点的最大值。
对于一个点来说,如果选了这个点,就不能选择他的子节点;如果不选这个点,他的子节点又有选和不选两种情况。
所以可以得出转移方程:
dp[x][1]=1;///初始化 dp[x][1]+=dp[j][0]; dp[x][0]+=max(dp[j][0],dp[j][1]); ///j是x的子节点
然后就可以利用dfs从子节点的信息推出父节点的信息。
因为s是必须住的,所以答案就是dp[s] [1];
思路:
#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int>PII;
#define I_int ll
inline ll read()
{
ll x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
char F[200];
inline void out(I_int x) {
if (x == 0) return (void) (putchar('0'));
I_int tmp = x > 0 ? x : -x;
if (x < 0) putchar('-');
int cnt = 0;
while (tmp > 0) {
F[cnt++] = tmp % 10 + '0';
tmp /= 10;
}
while (cnt > 0) putchar(F[--cnt]);
cout<<endl;
}
const int maxn=500000+10;
struct node{
int e,ne;
}a[maxn*2];
int h[maxn*2],idx;
int dp[maxn][2];
void add(int u,int v){
a[idx].e=v,a[idx].ne=h[u],h[u]=idx++;
}
void dfs(int u,int fa){
dp[u][1]=1;
for(int i=h[u];~i;i=a[i].ne){
int j=a[i].e;
if(j==fa) continue;
dfs(j,u);
dp[u][0]+=max(dp[j][0],dp[j][1]);
dp[u][1]+=dp[j][0];
}
}
int main(){
memset(h,-1,sizeof h);
idx=0;
int n=read(),s=read();
for(int i=1;i<n;i++){
int x=read(),y=read();
add(x,y);add(y,x);
}
dfs(s,-1);
out(dp[s][1]);
return 0;
}

京公网安备 11010502036488号