题意:
给定n个点的树,
你现在有k种颜料,你需要给每个点涂上其中一种,使得树满足:
对于任意两点x和y,如果它们之间的距离<=2,那么它们颜色不同,
问有多少种涂色方案,答案对1e9+7取模。
数据范围:n<=1e5
解法:
将树转换为有根树就好做了,
令1号点为根,假设树是这样的:
先给点1涂色,显然方案数为k,
对于1的字节点234,它们的颜色必须互不相同,那么方案数为A(k-1,3),
k要减1是因为要去掉1号点的颜色,同时用的是A()而不是C(),是因为涂色方案是有序的。
对于4的子节点5,方案数为A(k-2,1),k要减2是因为要去掉4号点和1号点的颜色。
综上:
设点x的儿子数量为d(x),
1号点对答案的贡献为k*A(k-1,d[1]),
其他点对答案的贡献为A(k-2,d[i]),
乘起来就是答案。
code:
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define PI pair<int,int>
const int maxm=1e5+5;
const int mod=1e9+7;
vector<int>g[maxm];
int fac[maxm];
int inv[maxm];
int d[maxm];
int n,k;
int ppow(int a,int b,int mod){
int ans=1%mod;a%=mod;
while(b){
if(b&1)ans=ans*a%mod;
a=a*a%mod;
b>>=1;
}
return ans;
}
void dfs(int x,int fa){
for(int v:g[x]){
if(v==fa)continue;
dfs(v,x);
d[x]++;
}
}
void init(){
fac[0]=1;
for(int i=1;i<maxm;i++)fac[i]=fac[i-1]*i%mod;
inv[maxm-1]=ppow(fac[maxm-1],mod-2,mod);
for(int i=maxm-2;i>=0;i--)inv[i]=inv[i+1]*(i+1)%mod;
}
int A(int n,int m){
if(m<0||m>n)return 0;
return fac[n]*inv[n-m]%mod;
}
signed main(){
init();
cin>>n>>k;
for(int i=1;i<n;i++){
int a,b;cin>>a>>b;
g[a].push_back(b);
g[b].push_back(a);
}
dfs(1,1);
int ans=k*A(k-1,d[1])%mod;
for(int i=2;i<=n;i++){
ans=ans*A(k-2,d[i])%mod;
}
cout<<ans<<endl;
return 0;
}