20200407 树
题意转化
将一棵树剖分为若干个颜色不同的联通块,求数目。
题解
这种题目第一反应就是树形dp,但是由于涉及到联通块,所以应当和 dfs 序有一定的关系。
dfs 序可以将一个树形结构映射到一个序列上,从而实现一些操作。
树链剖分就是按照特定的顺序对树进行 dfs 序标定,之后通过如线段树之类的数据结构进行维护完成的。
此外,通过入栈出栈都记录的 dfs 序,可以实现求 LCA 。
设  代表在 dfs 序上前 
 个点,使用 
 种颜色染色的方案数。
考虑  有两种获得贡献的来源:
- 一是和父亲涂一样的颜色
- 二是自己新开一种颜色
得到方程如下: 。
边界是  。
答案为 
Code
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn = 300 + 7;
const int maxm = 600 + 7;
const int mod = 1000000007;
int n, k;
int Head[maxn], to[maxm], Next[maxm], tot;
LL dp[maxn][maxn];
void addedge(int x, int y) {
    to[++tot] = y, Next[tot] = Head[x], Head[x] = tot;
}
void add(int x, int y) {
    addedge(x, y);
    addedge(y, x);
}
template < typename Tp >
void read(Tp &x) {
    x = 0; int fh = 1; char ch = 1;
    while(ch != '-' && (ch < '0' || ch > '9')) ch = getchar();
    if(ch == '-') fh = -1, ch = getchar();
    while(ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar();
    x *= fh;
}
void Init(void) {
    read(n); read(k);
    for(int i = 1, x, y; i < n; i++) {
        read(x); read(y);
        add(x, y);
    }
}
void Work(void) {
    dp[0][0] = 1;
    for(int i = 1; i <= n; i++) {
        for(int j = 1; j <= k; j++) {
            dp[i][j] = (dp[i - 1][j] + (dp[i - 1][j - 1]*(k - j + 1))) % mod;
        }
    }
    LL ans = 0;
    for(int i = 1; i <= k; i++) ans = (ans + dp[n][i]) % mod;
    printf("%lld\n",ans);
}
int main(void) {
    Init();
    Work();
    return 0;
} 
 京公网安备 11010502036488号
京公网安备 11010502036488号