原问题求树上的最大独立集
Solution:仔细读题,一开始以为每次选择的地点是连续的,导致求成最大深度了。实际上是最大独立集。
debug:对于每个儿子的贡献需要累加,叶子节点需要赋初值。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| vector<int>e[N]; int dp[N][2]; void dfs(int u,int fa){ dp[u][1]=1; for(auto v:e[u]){ if(v==fa)continue; dfs(v,u); dp[u][1]+=dp[v][0]; dp[u][0]+=max(dp[v][1],dp[v][0]); } } void solve(){ int rt;cin>>n>>rt; for(int i=1;i<=n-1;i++){ int u,v;cin>>u>>v; e[u].push_back(v); e[v].push_back(u); }
dfs(rt,0); int ans=dp[rt][1];
cout<<ans<<endl; }
|
伪装成树上dp的树上贪心
题意:给定一棵树,树上每个节点都有一个权值k[i],表示如果染色这个点到根的树链上能免费染色距离i不超过k[i]的点,求最少染色次数
Solution:贪心还是需要慢慢分析,中间更新最大值也算dp(bushi).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
|
int k[N]; int f[N];
int cnt=0; vector<int>e[N]; void dfs(int x){ for(auto v:e[x]){ dfs(v); k[x]=max(k[x],k[v]-1); f[x]=max(f[x],f[v]-1); } if(f[x]==0){ f[x]=k[x]; cnt++; } } void solve(){ cin>>n; for(int i=2;i<=n;i++){ int x;cin>>x; e[x].push_back(i); } for(int i=1;i<=n;i++)cin>>k[i]; dfs(1); cout<<cnt<<endl; }
|
https://www.nowcoder.com/discuss/353157393250983936?sourceSSR=search
求树的重心
Solution:只需要枚举每个点,比较重儿子大小和父节点以上的大小,比较出最大连通块大小的最小值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| int sz[N]; int son[N]; vector<int>e[N]; void dfs(int u,int fa){ sz[u]=1; for(auto v:e[u]){ if(v==fa)continue; dfs(v,u); if(son[u]<sz[v])son[u]=sz[v]; sz[u]+=sz[v]; } } void solve(){ while(cin>>n){ for(int i=1;i<=n;i++)e[i].clear(); fill(sz,sz+n+1,0); for(int i=1;i<=n-1;i++){ int u,v;cin>>u>>v; e[u].push_back(v); e[v].push_back(u); } dfs(1,0); int ans=1e9;int pos=0; for(int i=1;i<=n;i++){ int tmp=max(son[i],n-sz[i]); if(ans>tmp){ ans=tmp; pos=i; } } cout<<pos<<" "<<ans<<endl; } }
|
树上问题选讲 - hztmax0 - 博客园 (cnblogs.com)
222222222222222树形背包总结 - lnzwz - 博客园 (cnblogs.com)
刷题:ACM 树上背包DP总结 - liweihang - 博客园 (cnblogs.com)