感受
被题解惊呆了,真没想到可以转化为DFS序,然后在链上思考这个问题!
学到了


思路
首先我们要明确染色策略,按照DFS序染***r>当我们染色到u点时,假如我们已经使用了k种颜色。
按照DFS序染色的规则,我们可以发现,u点的子树并没有被染色,相反u的的父亲,父亲的父亲,...,都一定被染色了,至于它的兄弟也可能被染色。
所以,我们考虑给u染色时,如果u染的颜色来自那k种,那么染的颜色一定与父亲相同,否则,肯定可以从u的非子树部分找到一个点,其颜色与u相同,这样的话,根据树的性质,u必须经过父亲才能到达那个点,这样就会产生冲突。
如果染非k的颜色话,可以随便染,一定不会冲突。
因此,DP转移式子
-

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 300 + 10;
const ll mod = 1e9 + 7;
struct edge{
    int v, nex;
}e[maxn * 2];
int head[maxn], cnt;
int n, k;
ll dp[maxn][maxn];
void add_edge(int u, int v){
    cnt++;
    e[cnt] = (edge){v, head[u]};
    head[u] = cnt;
}
int main(){
    scanf("%d%d", &n, &k);
    int u, v;
    for(int i = 1; i < n; i++){
        scanf("%d%d", &u, &v);
        //add_edge(u, v); add_edge(v, u);
    }
    dp[1][1] = k;
    ll ans = 0;
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= k && i >= j; j++){
            if(i == 1 && j == 1) continue;
            dp[i][j] = dp[i - 1][j] + dp[i - 1][j - 1] * (k - j + 1);
            dp[i][j] %= mod;
            if(i == n) ans += dp[i][j], ans %= mod;
        }
    }
    printf("%lld\n", ans);
    return 0;
}