昨天的牛客鴿了,我不會數學
首先第一步要理解題意就是要把樹分成多個聯通塊,每個聯通塊的顏色都要不一樣,求方案數。
爲什麼每個聯通塊的顏色都不一樣,因爲如果有同樣的顏色在不同的聯通塊上的話就無法滿足題意,這兩個點之間的路徑的所有點就不會是都是同一種色。
用f[i][j]代表的是以i爲根的子樹分成j個聯通塊的的方案數。由於我沒想到大佬說的分成j個聯通塊就是刪掉j-1條邊,所以就硬算去合併每個子樹的答案。
暴力合併就複雜度變成n^3;
得到每種聯通塊的方案數後就是組合數學算一下就好了,有j個聯通塊,就是在k種色裏選j個,然後在全排列
vector<int>xian[max_];
int f[max_][max_],n,k,cal[2][max_];
void dfs(int now, int fa) {
for (auto to : xian[now]) {
if (to == fa)continue;
dfs(to, now);
}
memset(cal, 0, sizeof(cal));
int last = 1;
cal[0][1] = 1;
for (auto to : xian[now]) {
if (to == fa)continue;
memset(cal[last], 0, sizeof(cal[last]));
for (int i = 1; i <= k; i++) {
for (int j = 1; j <= k; j++) {
cal[last][i + j] += cal[last ^ 1][i] * f[to][j]; cal[last][i + j] %= mod;
cal[last][i + j - 1] += cal[last ^ 1][i] * f[to][j]; cal[last][i + j - 1] %= mod;
}
}
last ^= 1;
}
for (int i = 1; i <= k; i++) {
f[now][i] = cal[last ^ 1][i];
}
}
int value[max_];
signed main() {
n = read(), k = read();
for (int i = 2; i <= n; i++) {
int a = read(), b = read();
xian[a].push_back(b);
xian[b].push_back(a);
}
dfs(1, 0);
/*for (int i = 1; i <= k; i++) {
cout << f[1][i] << endl;
}*/
value[1] = k;
for (int i = 1; i <= 300; i++) {
value[i + 1] = value[i] * (k - i);
value[i + 1] %= mod;
}
int ans = 0;
for (int i = 1; i <= k; i++) {
ans += f[1][i] * value[i];
ans %= mod;
}
//cout << endl;
cout << ans;
return 0;
}