您的位置:首页 > 其它

牛客网 Wannafly模拟赛2 树 dp+思维

2017-08-29 20:25 218 查看
题目链接

题意:

shy有一颗树,树有n个结点。有k种不同颜色的染料给树染色。一个染色方案是合法的,当且仅当对于所有

相同颜色的点对(x,y),x到y的路径上的所有点的颜色都要与x和y相同。请统计方案数。

思路:

这个题真的很不好想,只要想到了就很简单了,当然我也没想,因为没机会啊


 

根据题意的描述,所有被染成同一个颜色的都是一个连通图,也就是很多个子树,你将这棵树用多少种颜色染色,拆分

出来之后就会有多少个子树,每个子树当中节点的颜色一样.

那么我们就可以用dp来简单计数,dp[i][j] 表示 i个点染成j个颜色的方案数.那么有:

dp[i][j] = dp[i-1][j]+dp[i-1][j-1]*(k-(j-1))

即第i个点要么和第i-1个点颜色相同,要么不同,不同的话前面用过的颜色都不能用了,还剩k-j+1种颜色.

PS : 也可以这样想,你把n个点,按照颜色相同的看成一个连通块,总能对应树上的一种染色方法,每一个连通块就是子树.

#include<bits/stdc++.h>

using namespace std;

const int maxn = 333;
typedef long long ll;
const ll mod = 1e9 + 7;

ll dp[maxn][maxn];
int n,k;
int main()
{
while(~scanf("%d %d",&n,&k))
{
memset(dp,0,sizeof dp);
int a,b;
for(int i = 1;i < n;i++)
scanf("%d %d",&a,&b);
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);
dp[i][j] %= mod;
}
}
ll ans = 0;
for(int i = 1;i <= k;i++)
ans = (ans + dp
[i]) % mod;
printf("%lld\n",ans);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: