首先,这道题正解的思路是从subtask2而得来的,因此先讲一下subtask2的作法。spa
由于保证答案不超过long long,因此直接求最大权独立集便可:dp[u][0]表示u点必定不能取的答案,dp[u][1]表示u点对儿子没有限制的答案。code
\(dp[u][0]=max(dp[v][0],dp[v][1])\)blog
\(dp[u][1]=max(dp[u][1],val[u]*\prod dp[v][0])\)class
直接跑DP便可。im
而正解是怎么作的呢?统计
想到乘法,能够将其转化为对数,每次乘法就至关于对数相加,这个就能够计算出怎样选取这个最大权独立集,再跑一遍深搜统计答案便可。db
//这里的dp的都是对数,因此只用相加便可 void dfs(int u,int fa) { dp[u][0]=dp[u][1]=0; for(int i=head[u];i;i=nxt[i]) { int v=to[i]; if(v!=fa) { dfs(v,u); dp[u][0]+=max(dp[v][0],dp[v][1]); dp[u][1]+=dp[v][0]; } } dp[u][1]+=logv[u]; }
\\统计答案的时候经过已经求出来的dp来做决策 \\若是u自己被选,确定儿子不可选 \\若是u自己没有被选,判断儿子选更优仍是不选更优。 \\选的话要乘上val long long dfs1(int u,int fa,int yes) { long long ans=1; for(int i=head[u];i;i=nxt[i]) { int v=to[i]; if(v!=fa) { if(yes) { ans=(ans*dfs1(v,u,0))%mod; }else{ if(dp[v][0]>dp[v][1]) { ans=(ans*dfs1(v,u,0))%mod; }else{ ans=(ans*dfs1(v,u,1))%mod; } } } } if(yes) { ans=(ans*val[u])%mod; } return ans; } if(dp[1][0]>dp[1][1]) { printf("%lld\n",dfs1(1,-1,0)); }else{ printf("%lld\n",dfs1(1,-1,1)); }