【换根DP+容斥】P3047 [USACO12FEB]Nearby Cows G

桃扇骨 2024-03-22 17:51 104阅读 0赞

P3047 [USACO12FEB]Nearby Cows G - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

题意:

3a35b6178f1f45949716ab3f3c2821a7.png

思路:

做法就是换根

994b1cc03c5e44688798d98c1d742f59.jpeg

预处理dp[v][j]用普通的树形DP处理即可

注意:一开始预处理的dp[v][j]指的是在v的子树里离v为j的权值和

Code:

  1. #include <bits/stdc++.h>
  2. #define int long long
  3. #define max(a,b) (a>b?a:b)
  4. #define min(a,b) (a<b?a:b)
  5. using namespace std;
  6. const int mxn=3e6+10;
  7. const int mxe=3e5+10;
  8. const int mod=1e9+7;
  9. struct ty{
  10. int to,next;
  11. }edge[mxe<<2];
  12. int N,K,u,v,x,tot=0;
  13. int head[mxn],dp[mxn][22];
  14. void add(int u,int v){
  15. edge[tot].to=v;
  16. edge[tot].next=head[u];
  17. head[u]=tot++;
  18. }
  19. void G_init(){
  20. tot=0;
  21. for(int i=0;i<=N;i++){
  22. head[i]=-1;
  23. }
  24. }
  25. void dfs1(int u,int fa){
  26. for(int i=head[u];~i;i=edge[i].next){
  27. if(edge[i].to==fa) continue;
  28. dfs1(edge[i].to,u);
  29. for(int j=1;j<=K;j++){
  30. dp[u][j]+=dp[edge[i].to][j-1];
  31. }
  32. }
  33. }
  34. void dfs2(int u,int fa){
  35. for(int i=head[u];~i;i=edge[i].next){
  36. if(edge[i].to==fa) continue;
  37. for(int j=K;j>=2;j--){
  38. dp[edge[i].to][j]-=dp[edge[i].to][j-2];
  39. }
  40. for(int j=1;j<=K;j++){
  41. dp[edge[i].to][j]+=dp[u][j-1];
  42. }
  43. dfs2(edge[i].to,u);
  44. }
  45. }
  46. void solve(){
  47. cin>>N>>K;
  48. G_init();
  49. for(int i=1;i<=N-1;i++){
  50. cin>>u>>v;
  51. add(u,v);
  52. add(v,u);
  53. }
  54. for(int i=1;i<=N;i++){
  55. cin>>x;
  56. dp[i][0]=x;
  57. }
  58. dfs1(1,0);
  59. dfs2(1,0);
  60. for(int i=1;i<=N;i++){
  61. int ans=0;
  62. for(int j=0;j<=K;j++) ans+=dp[i][j];
  63. cout<<ans<<'\n';
  64. }
  65. }
  66. signed main(){
  67. ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
  68. int __=1;//cin>>__;
  69. while(__--)solve();return 0;
  70. }

2023.10.7 upd:

换根原来有通用写法,学会了,严格鸽是我爹

a5fe0d1bf9ca414c9a43b33d5b18776f.png

  1. #include <bits/stdc++.h>
  2. #define int long long
  3. using i64 = long long;
  4. #define lowbit(x) (x & (- x))
  5. constexpr int N = 1e5 + 10;
  6. constexpr int mod = 1e9 + 7;
  7. constexpr int Inf = 0x3f3f3f3f;
  8. constexpr double eps = 1e-10;
  9. int n, k;
  10. int c[N];
  11. int dp[N][33];
  12. std::vector<int> adj[N];
  13. void dfs1(int u, int fa) {
  14. for (auto v : adj[u]) {
  15. if (v == fa) continue;
  16. dfs1(v, u);
  17. for (int j = 1; j <= k; j ++) {
  18. dp[u][j] += dp[v][j - 1];
  19. }
  20. }
  21. }
  22. void dfs2(int u, int fa) {
  23. for (auto v : adj[u]) {
  24. if (v == fa) continue;
  25. std::vector<int> a(33);
  26. for (int j = 1; j <= k; j ++) {
  27. dp[u][j] -= dp[v][j - 1];
  28. a[j - 1] = dp[v][j - 1];
  29. }
  30. for (int j = 1; j <= k; j ++) {
  31. dp[v][j] += dp[u][j - 1];
  32. }
  33. dfs2(v, u);
  34. for (int j = 1; j <= k; j ++) {
  35. dp[u][j] += a[j - 1];
  36. }
  37. }
  38. }
  39. void solve() {
  40. std::cin >> n >> k;
  41. for (int i = 1; i <= n - 1; i ++) {
  42. int u, v;
  43. std::cin >> u >> v;
  44. adj[u].push_back(v);
  45. adj[v].push_back(u);
  46. }
  47. for (int i = 1; i <= n; i ++) std::cin >> c[i];
  48. for (int i = 1; i <= n; i ++) {
  49. dp[i][0] = c[i];
  50. }
  51. dfs1(1, 0);
  52. dfs2(1, 0);
  53. for (int i = 1; i <= n; i ++) {
  54. int ans = 0;
  55. for (int j = 0; j <= k; j ++) ans += dp[i][j];
  56. std::cout << ans << "\n";
  57. }
  58. }
  59. signed main() {
  60. std::ios::sync_with_stdio(false);
  61. std::cin.tie(nullptr);
  62. int t = 1;
  63. while(t --) {
  64. solve();
  65. }
  66. return 0;
  67. }

发表评论

表情:
评论列表 (有 0 条评论,104人围观)

还没有评论,来说两句吧...

相关阅读