《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
原文地址:https://www.cnblogs.com/zwjzwj/p/15131015.html