zoukankan      html  css  js  c++  java
  • 《AtCoder Beginner Contest 207 F

    这题非常好。

    dp[i][j][3] - 以i为根的子树保护了j个点的方案数,0 - 未放置自己,且没被子节点保护,1 - 未放置自己,被子节点保护,2 - 放置了自己.

    这里的转移从所有子节点的状态转移过来来想比较好。

    这里主要有一点就是会存在增加新节点的情况。

    1:自己没有放置,但是被子节点覆盖了。

    2:子节点没有放置,但是被父节点覆盖了。

    这里的转移很显然是树形背包,理论上复杂度应该是n ^ 3.

    这里有个非常好的优化,动态维护size,这样可以保证每对点都在LCA处合并了一次,复杂度即为nlogn。

    还有就是为了去除重复计方案的情况,我们每次都开个空的数组f来存答案。

    // Author: levil
    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    typedef pair<LL,int> pii;
    const int N = 2005;
    const int M = 2e3 + 5;
    const LL Mod = 1e9 + 7;
    #define pi acos(-1)
    #define INF 1e9
    #define dbg(ax) cout << "now this num is " << ax << endl;
    
    int n,sz[N];
    vector<int> G[N];
    LL dp[N][N][3],f[N][3];//dp[i][j] - 以i为根的子树保护了j个点的方案数,0 - 未放置自己,且没被子节点保护,1 - 未放置自己,被子节点保护,2 - 放置了自己
    LL ADD(LL a,LL b) {
        return (a + b) % Mod;
    }
    void dfs(int u,int fa) {
        sz[u] = 1;
        dp[u][0][0] = 1;
        dp[u][1][2] = 1;
        for(auto v : G[u]) {
            if(v == fa) continue;
            dfs(v,u);
            memset(f,0,sizeof(f));
            for(int i = sz[u];i >= 0;--i) {
                for(int j = sz[v];j >= 0;--j) {
                    f[i + j][0] = ADD(f[i + j][0],dp[u][i][0] * ADD(dp[v][j][0],dp[v][j][1]) % Mod);
                    f[i + j + 1][1] = ADD(f[i + j + 1][1],dp[u][i][0] * dp[v][j][2] % Mod);
                    f[i + j][1] = ADD(f[i + j][1],dp[u][i][1] * ADD(dp[v][j][2],ADD(dp[v][j][0],dp[v][j][1])) % Mod);
                    f[i + j][2] = ADD(f[i + j][2],dp[u][i][2] * ADD(dp[v][j][1],dp[v][j][2]) % Mod);
                    f[i + j + 1][2] = ADD(f[i + j + 1][2],dp[u][i][2] * dp[v][j][0] % Mod);
                }
            }
            for(int i = sz[u] + sz[v];i >= 0;--i) {
                dp[u][i][0] = f[i][0];
                dp[u][i][1] = f[i][1];
                dp[u][i][2] = f[i][2];
            }
            sz[u] += sz[v];
        }
    
    }
    int main() {
        scanf("%d",&n);
        for(int i = 1;i < n;++i) {
            int x,y;scanf("%d %d",&x,&y);
            G[x].push_back(y);
            G[y].push_back(x);
        }
        dfs(1,0);
        for(int i = 0;i <= n;++i) printf("%lld
    ",(dp[1][i][0] + dp[1][i][1] + dp[1][i][2]) % Mod);
    
        system("pause");
        return 0;
    }
    View Code
  • 相关阅读:
    去中心化共识
    创建你的第一个去中心化应用(dapp)
    务实的去中心化
    什么是去中心化市场(OpenBazaar)
    为什么要做去中心化市场(OpenBazaar)
    区块链让物联网真正实现去中心化
    去中心化市场OpenBazaar如何运转
    如何安装去中心化市场(OpenBazaar)
    android自定义View&自定义ViewGroup(上)
    android自定义View&自定义ViewGroup(上)
  • 原文地址:https://www.cnblogs.com/zwjzwj/p/15131015.html
Copyright © 2011-2022 走看看