codeforces 1332 F. Independent Set(樹形dp)

題目鏈接:https://codeforc.es/contest/1332/problem/F

思路:這題選的是除了空集之外邊的子集,一開始做了個聯通子圖的,自閉了好久。這題可以先考慮選的邊是全集怎麼做,邊是全集很明顯可以用dp[u][1]表示這個點染色了的獨立集數目,dp[u][0]表示這個點沒染色的獨立集數目。轉移方程也很顯然,如果當前點染色了,那麼它的兒子必須是沒染色的,否則它的兒子可以是任何顏色。轉移方程也很顯然

$$dp[u][0]=\prod (dp[v][1]+dp[v][0])$$

$$dp[u][1]=\prod dp[v][0]$$

對於這個題只要加上一個狀態dp[u][2]表示u點和它每個兒子都斷開的方案數就行了,用qw[v]表示父節點與v斷開,v子樹的所有方案數,對於dp[u][1]和dp[u][0]來說如果u-v這條邊被刪掉了,那麼v這顆子樹怎麼選都是可以的,所以轉移時需要加上qw[v]的情況,而對於dp[u][2]來說由於每個兒子都斷開了,那麼它的方案數就是兒子節點qw[v]的乘積,需要這個狀態的原因是由於和兒子都斷開後,這個點變成了一個獨立的點,那麼其實它怎麼染色都無所謂,但dp[v][0]+dp[v][1]重複計算了這種情況,在計算qw[v]的時候需要把這種重複情況減去

qw[v]=dp[v][1]+dp[v][0]-dp[v][2]

dp[u][0]=\prod dp[v][1]+dp[v][0]+qw[v]

$$dp[u][1]=\prod dp[v][0]+qw[v]$$

$$dp[u][2]=\prod qw[v]$$

需要注意的是最後的答案需要減去空集的情況

#pragma GCC optimize(2)
#include <bits/stdc++.h>
#include <ext/pb_ds/priority_queue.hpp>
using namespace __gnu_pbds;
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const ll inff = 0x3f3f3f3f3f3f3f3f;
#define FOR(i,a,b) for(int i(a);i<=(b);++i)
#define FOL(i,a,b) for(int i(a);i>=(b);--i)
#define REW(a,b) memset(a,b,sizeof(a))
#define inf int(0x3f3f3f3f)
#define si(a) scanf("%d",&a)
#define sl(a) scanf("%I64d",&a)
#define sd(a) scanf("%lf",&a)
#define ss(a) scanf("%s",a)
#define mod ll(998244353)
#define pb push_back
#define eps 1e-6
#define lc d<<1
#define rc d<<1|1
#define Pll pair<ll,ll>
#define P pair<int,int>
#define pi acos(-1)
#define VI vector<vector<int>>
using namespace std;
const int N=3e5+8;
ll n,x,y,dp[N][3],ans;
vector<int>g[N];

void dfs(int u,int fa)
{
    dp[u][0]=dp[u][1]=dp[u][2]=1;
    for(int i=0;i<g[u].size();i++)
    {
        int v=g[u][i];
        if(v==fa) continue;
        dfs(v,u);
        ll qw=(dp[v][0]+dp[v][1]-dp[v][2]+mod)%mod;
        dp[u][0]=dp[u][0]*(dp[v][0]+dp[v][1]+qw)%mod;
        dp[u][1]=dp[u][1]*(dp[v][0]+qw)%mod;
        dp[u][2]=dp[u][2]*qw%mod;
    }
}
int main()
{
    cin.tie(0);
    cout.tie(0);
    cin>>n;
    FOR(i,1,n-1)
    {
        sl(x),sl(y);
        g[x].pb(y);
        g[y].pb(x);
    }
    dfs(1,0);
    cout<<(dp[1][1]+dp[1][0]-dp[1][2]-1+mod)%mod<<endl;
    return 0;
}
/*
1
5
3 5 1 2 4
3 3 2 3 1
*/

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章