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

题目链接


题意:


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
 
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[n][i]) % mod;
        printf("%lld\n",ans);
    }
}

你可能感兴趣的:(其它,思维,dp)