牛客—— 旅游 (树形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; }