E69 树形DP P2899 [USACO08JAN] Cell Phone Network G
视频链接:E69 树形DP P2899 [USACO08JAN] Cell Phone Network G_哔哩哔哩_bilibili
E68 树形DP P2016 战略游戏 - 董晓 - 博客园 (cnblogs.com)
P2899 [USACO08JAN] Cell Phone Network G - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
// 树形DP O(n) #include <iostream> #include <cstring> #include <algorithm> using namespace std; const int N=20005; int idx,head[N],to[N],ne[N]; void add(int u,int v){ to[++idx]=v;ne[idx]=head[u];head[u]=idx; } int n,f[N][3]; //0自己/1儿子/2父亲 void dfs(int u,int fa){ int t=0;f[u][0]=1; for(int i=head[u];i;i=ne[i]){ int v=to[i]; if(v==fa) continue; dfs(v,u); f[u][0]+=min(f[v][0],min(f[v][1],f[v][2])); f[u][2]+=min(f[v][0],f[v][1]); if((f[t][0]-min(f[t][0],f[t][1])) >(f[v][0]-min(f[v][0],f[v][1]))) t=v; } f[u][1]=f[t][0]; //t为最优儿子 for(int i=head[u];i;i=ne[i]){ int v=to[i]; if(v==fa||v==t) continue; f[u][1]+=min(f[v][0],f[v][1]); } } int main(){ scanf("%d",&n); for(int i=1,u,v;i<n;i++) scanf("%d%d",&u,&v),add(u,v),add(v,u); f[0][0]=2e9; dfs(1,0); printf("%d",min(f[1][0],f[1][1])); }
P2458 [SDOI2006] 保安站岗 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
// 树形DP O(n) #include<bits/stdc++.h> using namespace std; const int N=1505; vector<int> e[N]; int n,p[N],fa[N],root; int f[N][3]; //0自己/1儿子/2父亲 void dfs(int u){ int t=0; f[u][0]=p[u]; for(int v:e[u]){ dfs(v); f[u][0]+=min(min(f[v][0],f[v][2]),f[v][1]); f[u][2]+=min(f[v][0],f[v][1]); if(f[t][0]-min(f[t][0],f[t][1]) >f[v][0]-min(f[v][0],f[v][1])) t=v; } f[u][1]=f[t][0]; for(int v:e[u]){ if(v==t) continue; f[u][1]+=min(f[v][0],f[v][1]); } } int main(){ scanf("%d",&n); for(int i=1,u,v,k,m;i<=n;++i){ scanf("%d %d %d",&u,&k,&m); p[u]=k; while(m--){ scanf("%d",&v); fa[v]=true; e[u].push_back(v); } } for(int i=1;i<=n;++i)if(!fa[i]){root=i;break;} f[0][0]=2e9; dfs(root); printf("%d\n",min(f[root][0],f[root][1])); }