换根DP
复习或者学习可以参考以下两篇文章:
【朝夕的ACM笔记】动态规划-换根DP
- 知乎 (zhihu.com)
[学习笔记]换根dp -
洛谷专栏 (luogu.com)
下面是对应的一些练习题目:(题单链接)
换根DP
- 题单 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
有一些题实在是太板子了,所以我就没怎么写注释了。
#include<bits/stdc++.h> using ll=long long; const int N=2e4+10; const int MAXN=1e6+10; const int INF=0x3f3f3f3f; const int mod=19650827; const int MAX=270007; typedef std::pair<int,int> pii; typedef std::pair<double,int> pdi; ll dp[MAXN]; ll size[MAXN]; ll depth[MAXN];
struct Edge { int from,to; }; std::vector<Edge> edge[MAXN];; void dfs1(int x,int fa) { size[x]=1; for(auto t:edge[x]) { int to=t.to; if(to==fa) continue; depth[to]=depth[x]+1; dfs1(to,x); size[x]+=size[to]; } } void dfs2(int x,int fa) { for(auto t:edge[x]) { int to=t.to; if(to==fa) continue; dp[to]=dp[x]-2*size[to]+size[1]; dfs2(to,x); } } void solve() { int n; std::cin>>n; for(int i=1;i<n;i++) { int u,v; std::cin>>u>>v; edge[u].push_back({u,v}); edge[v].push_back({v,u}); } dfs1(1,-1); for(int i=1;i<=n;i++) dp[1]+=depth[i]; dfs2(1,-1); ll ans=0; int pos=0; for(int i=1;i<=n;i++) { if(dp[i]>ans) { ans=dp[i]; pos=i; } } std::cout<<pos; } int main(){ std::ios::sync_with_stdio(false),std::cin.tie(nullptr); int t=1; while(t--)solve(); return 0; }
|
#include<bits/stdc++.h> using ll=long long; const int N=2e4+10; const int MAXN=1e5+10; const int INF=0x3f3f3f3f; const int mod=19650827; const int MAX=270007; typedef std::pair<int,int> pii; typedef std::pair<double,int> pdi; ll dp[MAXN]; ll size[MAXN]; ll depth[MAXN]; ll a[MAXN]; struct Edge { int from,to; }; std::vector<Edge> edge[MAXN];; void dfs1(int x,int fa) { size[x]=a[x]; for(auto t:edge[x]) { int to=t.to; if(to==fa) continue; depth[to]=depth[x]+1; dfs1(to,x); size[x]+=size[to]; } } void dfs2(int x,int fa) { for(auto t:edge[x]) { int to=t.to; if(to==fa) continue; dp[to]=dp[x]-(2*size[to]-size[1]); dfs2(to,x); } } void solve() { int n; std::cin>>n; for(int i=1;i<n;i++) { int u,v; std::cin>>u>>v; edge[u].push_back({u,v}); edge[v].push_back({v,u}); } for(int i=1;i<=n;i++) std::cin>>a[i]; dfs1(1,-1); for(int i=1;i<=n;i++) dp[1]+=depth[i]*a[i]; dfs2(1,-1); ll ans=LONG_LONG_MAX; for(int i=1;i<=n;i++) { ans=std::min(ans,dp[i]); } std::cout<<ans; } int main(){ std::ios::sync_with_stdio(false),std::cin.tie(nullptr); int t=1; while(t--)solve(); return 0; }
|
#include<bits/stdc++.h> using ll=long long; const int N=2e4+10; const int MAXN=2e5+10; const int INF=0x3f3f3f3f; const int mod=19650827; const int MAX=270007; typedef std::pair<int,int> pii; typedef std::pair<double,int> pdi; ll dp[MAXN]; ll size[MAXN]; ll depth[MAXN]; ll a[MAXN];
struct Edge { int from,to; }; std::vector<Edge> edge[MAXN];; void dfs1(int x,int fa) { size[x]=1; for(auto t:edge[x]) { int to=t.to; if(to==fa) continue; depth[to]=depth[x]+1; dfs1(to,x); size[x]+=size[to]; } } void dfs2(int x,int fa) { for(auto t:edge[x]) { int to=t.to; if(to==fa) continue; dp[to]=dp[x]-2*size[to]+size[1]; dfs2(to,x); } } void solve() { int n; std::cin>>n; for(int i=1;i<n;i++) { int u,v; std::cin>>u>>v; edge[u].push_back({u,v}); edge[v].push_back({v,u}); } dfs1(1,-1); for(int i=1;i<=n;i++) dp[1]+=size[i]; dfs2(1,-1); ll ans=0; for(int i=1;i<=n;i++) { ans=std::max(ans,dp[i]); } std::cout<<ans; } int main(){ std::ios::sync_with_stdio(false),std::cin.tie(nullptr); int t=1; while(t--)solve(); return 0; }
|
#include<bits/stdc++.h> using ll=long long; const int N=2e4+10; const int MAXN=2e5+10; const int INF=0x3f3f3f3f; const int mod=19650827; const int MAX=270007; typedef std::pair<int,int> pii; typedef std::pair<double,int> pdi; ll dp[MAXN]; ll size[MAXN]; ll depth[MAXN]; ll a[MAXN]; struct Edge { int from,to; }; std::vector<Edge> edge[MAXN];; void dfs1(int x,int fa) { size[x]=a[x]; for(auto t:edge[x]) { int to=t.to; if(to==fa) continue; depth[to]=depth[x]+1; dfs1(to,x); size[x]+=size[to]; } } void dfs2(int x,int fa) { for(auto t:edge[x]) { int to=t.to; if(to==fa) continue; dp[to]=dp[x]-(2*size[to]-size[1]); dfs2(to,x); } } void solve() { int n; std::cin>>n; for(int i=1;i<=n;i++) std::cin>>a[i]; for(int i=1;i<n;i++) { int u,v; std::cin>>u>>v; edge[u].push_back({u,v}); edge[v].push_back({v,u}); } dfs1(1,-1); for(int i=1;i<=n;i++) dp[1]+=depth[i]*a[i]; dfs2(1,-1); ll ans=0; for(int i=1;i<=n;i++) { ans=std::max(ans,dp[i]); } std::cout<<ans; } int main(){ std::ios::sync_with_stdio(false),std::cin.tie(nullptr); int t=1; while(t--)solve(); return 0; }
|
后续补
#include<bits/stdc++.h> using ll=long long; const int N=2e4+10; const int MAXN=1e5+10; const int INF=0x3f3f3f3f; const int mod=19650827; const int MAX=270007; typedef std::pair<int,int> pii; typedef std::pair<double,int> pdi; ll dp[MAXN]; ll size[MAXN]; ll depth[MAXN]; ll c[MAXN];
struct Edge { int from,to; ll val; }; std::vector<Edge> edge[MAXN];; void dfs1(int x,int fa) { size[x]=c[x]; for(auto t:edge[x]) { int to=t.to; if(to==fa) continue; depth[to]=depth[x]+t.val; dfs1(to,x); size[x]+=size[to]; } } void dfs2(int x,int fa) { for(auto t:edge[x]) { int to=t.to; if(to==fa) continue; dp[to]=dp[x]-(2*size[to]-size[1])*t.val; dfs2(to,x); } } void solve() { int n; std::cin>>n; for(int i=1;i<=n;i++) std::cin>>c[i]; for(int i=1;i<n;i++) { int a,b,l; std::cin>>a>>b>>l; edge[a].push_back({a,b,l}); edge[b].push_back({b,a,l}); } dfs1(1,-1); for(int i=1;i<=n;i++) dp[1]+=depth[i]*c[i]; dfs2(1,-1); ll ans=1e15; for(int i=1;i<=n;i++) { ans=std::min(ans,dp[i]); } std::cout<<ans; } int main(){ std::ios::sync_with_stdio(false),std::cin.tie(nullptr); int t=1; while(t--)solve(); return 0; }
|
后续补
#include<bits/stdc++.h> using ll=long long; const int N=2e4+10; const int MAXN=2e5+10; const int INF=0x3f3f3f3f; const int mod=19650827; const int MAX=270007; typedef std::pair<int,int> pii; typedef std::pair<double,int> pdi; ll dp[MAXN]; ll size[MAXN]; ll depth[MAXN]; ll a[MAXN]; struct Edge { int from,to; }; std::vector<Edge> edge[MAXN];; void dfs1(int x,int fa) { size[x]=1; for(auto t:edge[x]) { int to=t.to; if(to==fa) continue; depth[to]=depth[x]+1; dfs1(to,x); size[x]+=size[to]; } } void dfs2(int x,int fa) { for(auto t:edge[x]) { int to=t.to; if(to==fa) continue; dp[to]=dp[x]-(2*size[to]-size[1]); dfs2(to,x); } } void solve() { int n; std::cin>>n; for(int i=1;i<n;i++) { int u,v; std::cin>>u>>v; edge[u].push_back({u,v}); edge[v].push_back({v,u}); } dfs1(1,-1); for(int i=1;i<=n;i++) dp[1]+=depth[i]; dfs2(1,-1); for(int i=1;i<=n;i++) { std::cout<<dp[i]<<"\n"; } } int main(){ std::ios::sync_with_stdio(false),std::cin.tie(nullptr); int t=1; while(t--)solve(); return 0; }
|
#include<bits/stdc++.h> using ll=long long; const int N=2e4+10; const int MAXN=2e5+10; const int INF=0x3f3f3f3f; const int mod=19650827; const int MAX=270007; typedef std::pair<int,int> pii; typedef std::pair<double,int> pdi; ll dp[MAXN]; ll size[MAXN]; ll depth[MAXN]; struct Edge { int from,to; }; std::vector<Edge> edge[MAXN];; void dfs1(int x,int fa) { size[x]=1; for(auto t:edge[x]) { int to=t.to; if(to==fa) continue; depth[to]=depth[x]+1; dfs1(to,x); size[x]+=size[to]; } } void dfs2(int x,int fa) { for(auto t:edge[x]) { int to=t.to; if(to==fa) continue; dp[to]=dp[x]-2*size[to]+size[1]; dfs2(to,x); } } void solve() { int n; std::cin>>n; for(int i=1;i<n;i++) { int u,v; std::cin>>u>>v; edge[u].push_back({u,v}); edge[v].push_back({v,u}); } dfs1(1,-1); for(int i=1;i<=n;i++) dp[1]+=depth[i]; dfs2(1,-1); ll ans=1e9; int p=0; for(int i=1;i<=n;i++) { if(ans>dp[i]) { ans=dp[i]; p=i; } } std::cout<<p<<" "<<ans; } int main(){ std::ios::sync_with_stdio(false),std::cin.tie(nullptr); int t=1; while(t--)solve(); return 0; }
|
#include<bits/stdc++.h> using ll=long long; const int N=2e4+10; const int MAXN=1e5+10; const int INF=0x3f3f3f3f; const int mod=19650827; const int MAX=270007; typedef std::pair<int,int> pii; typedef std::pair<double,int> pdi;
ll dp[MAXN][25]; ll size[MAXN][25]; ll c[MAXN]; int n,k; struct Edge { int from,to; }; std::vector<Edge> edge[MAXN]; void dfs1(int x,int fa) { for(int i=0;i<=k;i++) size[x][i]=c[x]; for(auto t:edge[x]) { int to=t.to; if(to==fa) continue; dfs1(to,x); for(int i=1;i<=k;i++) { size[x][i]+=size[to][i-1]; } } } void dfs2(int x,int fa) { for(auto t:edge[x]) { int to=t.to; if(to==fa) continue; dp[to][1]+=size[x][0]; for(int i=2;i<=k;i++) { dp[to][i]+=dp[x][i-1]-size[to][i-2]; } dfs2(to,x); } } void solve() { std::cin>>n>>k; for(int i=1;i<n;i++) { int u,v; std::cin>>u>>v; edge[u].push_back({u,v}); edge[v].push_back({v,u}); } for(int i=1;i<=n;i++) std::cin>>c[i]; dfs1(1,-1); for(int i=1;i<=n;i++) { for(int j=0;j<=k;j++) { dp[i][j]=size[i][j]; } } dfs2(1,-1); for(int i=1;i<=n;i++) { std::cout<<dp[i][k]<<"\n"; } } int main(){ std::ios::sync_with_stdio(false),std::cin.tie(nullptr); int t=1; while(t--)solve(); return 0; }
|
后续补
#include<bits/stdc++.h> using ll=long long; const int N=2e4+10; const int MAXN=2e5+10; const int INF=0x3f3f3f3f; const int mod=19650827; const int MAX=270007; typedef std::pair<int,int> pii; typedef std::pair<double,int> pdi; ll dp[MAXN]; ll size[MAXN]; ll a[MAXN];
int n; struct Edge { int from,to; }; std::vector<Edge> edge[MAXN]; void dfs1(int x,int fa) { size[x]=a[x]; for(auto t:edge[x]) { int to=t.to; if(to==fa) continue; dfs1(to,x); if(size[to]>0) { size[x]+=size[to]; } } } void dfs2(int x,int fa) { for(auto t:edge[x]) { int to=t.to; if(to==fa) continue; if(size[to]>0) { dp[to]=std::max(size[to],dp[x]); } else { dp[to]=std::max(size[to],dp[x]+size[to]); } dfs2(to,x); } } void solve() { std::cin>>n; for(int i=1;i<=n;i++) { std::cin>>a[i]; if(a[i]==0) a[i]=-1; } for(int i=1;i<n;i++) { int u,v; std::cin>>u>>v; edge[u].push_back({u,v}); edge[v].push_back({v,u}); } dfs1(1,-1); dp[1]=size[1]; dfs2(1,-1); for(int i=1;i<=n;i++) { std::cout<<dp[i]<<" "; } } int main(){ std::ios::sync_with_stdio(false),std::cin.tie(nullptr); int t=1; while(t--)solve(); return 0; }
|