小凱的疑惑


首先,這道題正解的思路是從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));
}
相關文章
相關標籤/搜索