当前位置:   article > 正文

【题解】wzpakioi(CF1120D)(2019,5.16)

cf1120d power tree

Description

o_bbbb.PNG

Sample Input

5

5 1 3 2 1

1 2

2 3

2 4

1 5

Sample Output

4 1

Hint

n200000

Solution

这题一眼不可做。。。想用随机骗分,结果不会写判断答案是否合法。

正解树形DP,设计状态,我们发现其实在以 u 为根的子树中,最多只能有一个节点由节点 u 控制,所以其实我们可以设计状态 f[u][0/1] 表示当前节点 u 以他为根的子树中有 0/1 个节点没有被控制,需要当前节点控制。

其实已经被控制的点完全可以看成一个点,这样就可以发现最多只能有一个被当前节点控制,因为如果有两个要求被控制,那么他们的值是肯定不一样的,这样上面的节点只能整体加,而这两个节点没法自我调节。

转移:

t=vf[v][0]

f[u][0]=minvtf[v][0]+f[v][1]+cost[u]

当前这个儿子的子树中空一个节点让 u 控制

f[u][1]=minvtf[v][0]+f[v][1]

当前这个儿子的子树中空一个节点不控制

那么第一问就很好写了。

第二问要求我们统计方案,我们继续考虑用树形DP,设计状态 g[u][0/1] 为让 u 的子树全部被控制或者一个点不被控制的方案数,那么根据乘法原理,我们要把所有儿子的方案数乘起来得到这个节点的方案。

但是每个子树的方案是不一样的,因为我们更新时是有 空出一个节点的。

那么我们还得每个儿子遍历一下,看看他是不是空出一个节点,然后加法原理再都加起来。

All=vg[v][0]modP

g[u][0]=(f[u][0]==tf[v][0]+f[v][1]+cost[u])Allg[v][0]1g[v][1]

g[u][1]=(f[u][1]==tf[v][0]+f[v][1])Allg[v][0]1g[v][1]

最后注意一下如果 f[u][0]t 的话,要加上所有的方案数 All

Code

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. typedef long long LL;
  4. int n,m,MaxDepth;
  5. const int N=2e5+5,P=998244353;
  6. const LL INF=1e18;
  7. LL f[N][2],cost[N],g[N][2];
  8. int dep[N];
  9. vector <int> E[N];
  10. inline char gc(){
  11. static char buf[1<<20],*p1=buf,*p2=buf;
  12. if(p1==p2){
  13. p2=(p1=buf)+fread(buf,1,1<<20,stdin);
  14. if(p1==p2) return EOF;
  15. }
  16. return *p1++;
  17. }
  18. inline int read(){
  19. int x=0;char ch=gc();
  20. while(ch<'0' || ch>'9') ch=gc();
  21. while(ch<='9' && ch>='0') x=x*10+ch-'0',ch=gc();
  22. return x;
  23. }
  24. inline LL power(LL a,int b){
  25. LL ret=1;
  26. while(b){
  27. if(b&1) ret=(ret*a)%P;
  28. a=(a*a)%P;
  29. b>>=1;
  30. }
  31. return ret;
  32. }
  33. inline void dfs(int u,int fa){
  34. dep[u]=dep[fa]+1;
  35. if(E[u].size()==1 && E[u][0]==fa){
  36. f[u][1]=0;
  37. f[u][0]=cost[u];
  38. g[u][0]=g[u][1]=1;
  39. MaxDepth=dep[u];
  40. return;
  41. }
  42. LL t=0,All=1;
  43. for(int i=0;i<(int)E[u].size();++i){
  44. int v=E[u][i];
  45. if(v==fa) continue;
  46. dfs(v,u);
  47. t+=f[v][0];
  48. All=(All*g[v][0])%P;
  49. }
  50. f[u][0]=t;
  51. f[u][1]=INF;
  52. for(int i=0;i<(int)E[u].size();++i){
  53. int v=E[u][i];
  54. if(v==fa) continue;
  55. f[u][0]=min(f[u][0],t-f[v][0]+f[v][1]+cost[u]);
  56. f[u][1]=min(f[u][1],t-f[v][0]+f[v][1]);
  57. }
  58. if(f[u][0]==t) g[u][0]=All%P;
  59. for(int i=0;i<(int)E[u].size();++i){
  60. int v=E[u][i];
  61. if(v==fa) continue;
  62. LL ret=All*power(g[v][0],P-2)%P*g[v][1]%P;
  63. if(f[u][0]==t-f[v][0]+f[v][1]+cost[u]) g[u][0]=(g[u][0]+ret)%P;
  64. if(f[u][1]==t-f[v][0]+f[v][1]) g[u][1]=(g[u][1]+ret)%P;
  65. }
  66. }
  67. int main(){
  68. n=read();
  69. for(int i=1;i<=n;++i) cost[i]=read();
  70. for(int i=1;i<n;++i){
  71. int u=read(),v=read();
  72. E[u].push_back(v);
  73. E[v].push_back(u);
  74. }
  75. dfs(1,1);
  76. if(MaxDepth!=n) printf("%lld %lld\n",f[1][0],g[1][0]);
  77. else {
  78. int cnt=0;
  79. for(int i=1;i<=n;++i) cnt=(cnt+(cost[i]==f[1][0]))%P;
  80. printf("%lld %d\n",f[1][0],cnt);
  81. }
  82. return 0;
  83. }

转载于:https://www.cnblogs.com/JCNL666/p/10879365.html

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/菜鸟追梦旅行/article/detail/64659
推荐阅读
相关标签
  

闽ICP备14008679号