HDU 6091 - Rikka with Match

answer

Tree dp, design condition is as follows:
设 DP[u][i][0] 表示 以点 u 为根的子树 最大匹配数模 m 为 i 时,且 u 点没有匹配的方案数
DP[u][i][1] 表示 以点 u 为根的子树 最大匹配数模 m 为 i 时,且 u 点匹配上的方案数
Recursive formula is as follows:
DP[u][k][0](不匹配该节点) += ∑ [i+j==k] 2 * DP[u][i][0] * DP[v][j][1](此时u->这条边连不连都无所谓,所以*2) +  DP[u][i][0] * DP[v][j][0](儿子已近匹配了)
DP[u][k][1](该节点已经连了边) += ∑ [i+j==k] 2 * DP[u][i][1] * ( DP[v][j][0] + DP[v][j][1] )
DP[u][k][1] (该节点现在正要连边)+= ∑ [i+j==k-1(预留出一个位用于匹配)] DP[u][i][0] * DP[v][j][0](此时这条边必须存在并且u,v都不能匹配别的边)

Code

#include <the iostream> 
#include <CString> 
#include <cstdio> 
#include <Vector>
 the using  namespace STD;
 #define int Long Long
 #define MOD 998 244 353
 #define N 50001
 #define M 410 
Vector < int > VEC [N];
 int DP [N] [M] [ 2 ], size [N] / * record nodes to up to match the number edge * /, TEMP [M] [ 2 ] / * DP array in the middle of an update can not be changed, so with this array Instead of * /, m;
 void the Add ( int U, int V) // update the array using edge 
{ 
    Memset (TEMP, 0 , the sizeof(TEMP));
     for ( int I = 0 ; I <= size [U]; I ++ ) // where the time complexity can prove to n-* m 
    { 
        for ( int J = 0 ; J <= size [V]; J ++ ) 
        { 
            TEMP [I + J] [ 0 ] + = 2 * DP [U] [I] [ 0 ] * DP [V] [J] [ . 1 ] + DP [U] [I] [ 0 ] * DP [V] [J] [ 0 ]; 
            TEMP [I + J] [ 0 ]% = MOD; 
            TEMP [I + J] [ . 1 ] + = 2 * DP [U] [I] [ . 1 ] * (DP [ V] [J] [ 0]+dp[v][j][1]);
            temp[i+j][1]%=mod;
            temp[i+j+1][1]+=dp[u][i][0]*dp[v][j][0];
            temp[i+j+1][1]%=mod;
        }
    }
    for(int i=0;i<m;i++)//将temp复制到dp内
    {
        dp[u][i][0]=(temp[i][0]+temp[i+m][0])%mod;//i+j有可能超过n
        dp[u][i][1]=(temp[i][1]+temp[i+m][1])%mod;
    }
    size[u]=min(size[u]+size[v],m);//size[u]不能超过m,否则会数组出界。
}
void dfs(int id,int from)
{
    size[id]=1;
    dp[id][0][0]=1;
    for(int i=0;i<vec[id].size();i++)
    {
        int to=vec[id][i];
        if(to==from) continue;
        dfs(to,id);//树形dp的惯例,自底向上更新
        add(id,to);
    }
}
signed main()
{
    int n;
    cin>>n>>m;
    for(int i=1;i<n;i++) 
    {
        int a,b;
        scanf("%lld%lld",&a,&b);
        vec[a].push_back(b);
        vec[b].push_back(a);
    }
    dfs(1,0);
    cout<<(dp[1][0][0]+dp[1][0][1])%mod;
}

 

Guess you like

Origin www.cnblogs.com/linzhuohang/p/11305427.html