zoukankan      html  css  js  c++  java
  • HDU 6091

    思路来自 某FXXL

    不过复杂度咋算的..

    /*
    HDU 6091 - Rikka with Match [ 树形DP ]  |  2017 Multi-University Training Contest 5
    题意:
    	给出N个点的树,求去边的方案数使得 去边后最大匹配数是M的倍数
    	限制: N<=5e4, M<=200
    分析:
    	设 DP[u][i][0] 表示 以点 u 为根的子树 最大匹配数模 m 为 i 时,且 u 点没有匹配的方案数
    	   DP[u][i][1] 表示 以点 u 为根的子树 最大匹配数模 m 为 i 时,且 u 点匹配上的方案数
    	得到对于 u 的某个子节点 v 对 u 的更新(讨论(u,v)的边连与不连)
    		DP[u][k][0] += ∑ [i+j==k] 2 * DP[u][i][0] * DP[v][j][1] + 1 * 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节点的取值范围,即 size[u] = min(size[u]+size[v], m)   这样复杂度大概 O(nm)(???)
    */
    #include <bits/stdc++.h>
    using namespace std;
    #define LL long long
    const LL MOD = 998244353;
    const int N = 5e4+5;
    const int M = 205;
    vector<int> G[N];
    int t, n, m;
    int size[N];
    LL dp[N][M][2];
    LL tmp[M<<1][2];
    void solve(int u, int v)
    {
        memset(tmp, 0, sizeof(tmp));
        for (int i = 0; i <= size[u]; i++)
            for (int j = 0; j <= size[v]; j++)
            {
                tmp[i+j][1] += 2 * dp[u][i][1] * (dp[v][j][0]+dp[v][j][1]);
                tmp[i+j][1] %= MOD;
                tmp[i+j+1][1] += dp[u][i][0] * dp[v][j][0];
                tmp[i+j+1][1] %= MOD;
                tmp[i+j][0] += 2 * dp[u][i][0]*dp[v][j][1] + dp[u][i][0]*dp[v][j][0];
                tmp[i+j][0] %= MOD;
            }
        for (int i = 0; i < m; i++)
        {
            dp[u][i][0] = (tmp[i][0] + tmp[i+m][0]) % MOD;
            dp[u][i][1] = (tmp[i][1] + tmp[i+m][1]) % MOD;
        }
        size[u] =  min(m, size[u]+size[v]);
    }
    void dfs(int u, int pre)
    {
        memset(dp[u], 0, sizeof(dp[u]));
        dp[u][0][0] = 1;
        size[u] = 1;
        for (auto & v : G[u])
        {
            if (v == pre) continue;
            dfs(v, u);
            solve(u, v);
        }
    }
    int main()
    {
        scanf("%d", &t);
        while (t--)
        {
            scanf("%d%d", &n, &m);
            for (int i = 1; i <= n; i++) G[i].clear();
            for (int i = 1; i < n; i++)
            {
                int u, v; scanf("%d%d", &u, &v);
                G[u].push_back(v);
                G[v].push_back(u);
            }
            dfs(1, 1);
            int ans = (dp[1][0][0]+dp[1][0][1]) % MOD;
            printf("%d
    ", ans);
        }
    }
    

      

  • 相关阅读:
    根据 谷歌官网写一个 该浏览器上的扩展
    深度学习
    华为在线学习
    pandas 常规操作大全
    猎奇有些意思的
    LINUX 必知必会检测表--通读无关语言
    自动化部署三剑客 gitlab + ansible + jenkins
    python 框架
    delphi 多线程之System.TMonitor
    函数和对象 及 prototype和__proto__
  • 原文地址:https://www.cnblogs.com/nicetomeetu/p/7360556.html
Copyright © 2011-2022 走看看