• 2021icpc南京 H. Crystalfly


    Problem - H - CodeforcesCodeforces. Programming competitions and contests, programming communityhttps://codeforces.com/gym/103470/problem/H

    题意:有一棵树,每一个节点都有一个值val[i]表示这个点有多少只晶蝶,t[i]表示假设你到达该点连接的点之后,经过多少秒该点的晶蝶都会跑光(从一个点到另一个点花费时间为1).问最多可以抓多少晶蝶

    f[i][0]表示所有的子节点的值得不到的时候的子树答案最大值

    f[i][1]表示子树答案(取当前点)最大值

    f[x][0]的计算方法很简单,直接Σ(f[j][1]-val[j])即可,意为我们取

    这个点的子树的答案的最大值,但是不取当前的这个点.

    我们分情况讨论,分为两种情况,一种是我们在当前节点的下一层只得到

    一个点的值,另一种是当t[j]==3时我们先去的到另外一个点的权值再拐

    弯回到这个j点往下走的情况.

    下面分类讨论:

    1.当前父节点x的下一层子节点只获得一个点的情况,这个结果表示为

    f[x][1]=max(f[x][0]+val[y],f[x][1]),意为假设该节点的子节

    点都不取,然后取一个点的值的情况,这种情况其实包含了几种小情况,

    (1)获取当前点值直接往下走,(2)取了同层的一个点之后在拐弯过来

    不获取当前点的值往下走.但是由于是对于情况取max所以两种小情况

    都包含了.

    2.x的子节点j的t[j]==3,我们先去拐弯取一个点在回来按照j点往下

    走,和上面的拐弯一样要注意,拐弯处那个点的子节点的值我们都得不

    到,就可以按照上面的f[i][0]算.所以我们这里的状态转移方程式就

    是当t[j]==3

    f[x][1]=max(f[x][0]+val[j]+f[y][0]-f[y][1]+val[y],f[x][1])

    这里可以知道f[x][0]+val[j]是固定的值,那么只需要求

    temp=f[y][0]-f[y][1]+val[y]的最大值(j表示拐弯后往下那个点,y表

    示拐弯处的点),知道temp的最大值时候还要注意假设temp的这个t[y]==3

    的情况,我们就要维护一个最大值和一个次大值去求最值

    1. #include<bits/stdc++.h>
    2. #define ll long long
    3. using namespace std;
    4. const int N =1e5+10,mod=998244353;
    5. int val[N],t[N],h[N],tot=0;
    6. ll f[N][2];
    7. struct node
    8. {
    9. int to,ne;
    10. }edge[2*N];
    11. void add(int x,int y)
    12. {
    13. edge[++tot].to=y;
    14. edge[tot].ne=h[x];
    15. h[x]=tot;
    16. }
    17. void dfs(int x,int fa)
    18. {
    19. f[x][1]=0;
    20. f[x][0]=val[x];
    21. int max1=0,max2=0;
    22. for(int i=h[x];i!=-1;i=edge[i].ne)
    23. {
    24. int j=edge[i].to;
    25. if(j==fa)
    26. continue;
    27. dfs(j,x);
    28. f[x][0]+=(f[j][1]-val[j]);
    29. int temp=f[j][0]-f[j][1]+val[j];
    30. if(temp>=max1)
    31. {
    32. max2=max1;
    33. max1=temp;
    34. }
    35. else if(temp>=max2)
    36. max2=temp;
    37. }
    38. f[x][1]=f[x][0];
    39. for(int i=h[x];i!=-1;i=edge[i].ne)
    40. {
    41. int j=edge[i].to;
    42. if(j==fa)
    43. continue;
    44. f[x][1]=max(f[x][0]+val[j],f[x][1]);
    45. if(t[j]==3)
    46. {
    47. if(f[j][0]-f[j][1]+val[j]==max1)
    48. {
    49. f[x][1]=max(f[x][0]+val[j]+max2,f[x][1]);
    50. }
    51. else
    52. {
    53. f[x][1]=max(f[x][0]+val[j]+max1,f[x][1]);
    54. }
    55. }
    56. }
    57. }
    58. void solve()
    59. {
    60. memset(h,-1,sizeof h);
    61. tot=0;
    62. int n,x,y;
    63. cin>>n;
    64. for(int i=1;i<=n;i++)
    65. cin>>val[i];
    66. for(int i=1;i<=n;i++)
    67. cin>>t[i];
    68. for(int i=1;i<n;i++)
    69. {
    70. cin>>x>>y;
    71. add(x,y);
    72. add(y,x);
    73. }
    74. dfs(1,0);
    75. cout<<f[1][1]<<endl;
    76. }
    77. signed main()
    78. {
    79. cin.tie(0);
    80. cout.tie(0);
    81. ios::sync_with_stdio(0);
    82. int t;
    83. cin>>t;
    84. while(t--)
    85. solve();
    86. return 0;
    87. }

  • 相关阅读:
    Grid 布局
    力扣刷题-移除指定值的链表元素
    数据智能类API推荐
    dc_shell的change_names命令,信号[]/_
    AI智能电话客服机器人的交互流程
    【java核心技术】Java知识总结 -- 继承
    2023版 STM32实战12 IIC总线读写AT24C02
    Vue技术9.3
    前后端分离的项目——图书管理系统
    2022年,计算机视觉最常用的Python库
  • 原文地址:https://blog.csdn.net/qq_49593247/article/details/127402370