首先,這道題正解的思路是從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)); }