2017武汉大学校赛网络预选赛b题

来源:互联网 发布:妙味云课堂js视频下载 编辑:程序博客网 时间:2024/04/27 07:14

Input file: standard input
Output file: standard output
Time limit: 1 second
Memory limit: 512 mebibytes
When Asuho was just a little girl, she has been loving stars, as there are so many romantic stories about old legends and the stars.

Today, as usual, Asuho went to the observatory with her beloved boyfriend, Kogasaka Ming, to see the splendid sky of galaxy. Sitting with Kogasaka shoulder to shoulder, Asuho thought nothing could make her happier.

“Asuho,” Kogasaka called Asuho softly. “I have a question about the Hoshizora(night sky with stars).”

“What’s it?” Asuho answered, happily. “I know everything about the stories, you can ask anything.”

Kogasaka smiled, “You see the stars? Just imagine there are nn distinct stars in the sky while n-1n−1 relationships connect them. Each relationship is between two stars and all stars are connected directly or indirectly. Now you need to divide the nn stars into mm different types. Beware that no two directly connected stars should share the same type and some stars cannot be some types. I want you to tell me how many distinct solutions there could be.”

Suddenly the Stella meteor shower appeared, so the lovers forgot the question and started to admire the beautiful Hoshizora.

Asuho thought it was unbelievable that Kogasaka should ask her such a foolish question which she can’t solve. Of course she didn’t wish to reveal her poor math. So can you help her to tell the answer?

Input
The Input file contains several test cases.

For each case, the first line contains two integers nn (2\le n\le 10^42≤n≤10
​4
​​ ), mm (1\le m\le 201≤m≤20)

The next n-1n−1 lines, each line contains 2 integers x_ix
​i
​​ , y_iy
​i
​​ expressing relationships between the two stars.

The next nn lines, each lines contains m numbers and each of the mm is 0 or 1.

The ii-th number of the jj-th line respect whether jj-th star can be divided into the ii-th type. 1 means it could while 0 means not.

Output
For each test case, output one single line, containing the number of solutions module 10^7+910
​7
​​ +9
Examples
Input 1
4 6
1 2
1 3
1 4
1 1 1 1 1 0
1 1 1 1 1 1
1 1 1 1 1 1
1 1 1 1 1 1
Output 1
625

题意:给你一棵树,给树上每个顶点涂色,相连的顶点颜色不能相同,问你有多少中涂色的方式。

解题思路:树dp,dp[i][j]表示以i为根的子树,i涂上颜色j的种类数。具体思路看代码注释。比赛的时候和队友各种暴力找,还是做的题少了,没有往这方面想。

#include<bits/stdc++.h>using namespace std;typedef long long ll;const int maxn = 1e4 + 10;const ll mod = 1e7 + 9;int n,m;int c[maxn][30];//第i个点的是否可涂颜色jvector<int> Tree[maxn];//i的儿子vector<int> g[maxn];//图的邻接表ll dp[maxn][30];//dp[i][j] 以顶点i为根的子树,染上颜色j的种类数bool visit[maxn];void init()//初始化{    memset(visit,false,sizeof(visit));    for(int i = 1; i <= n; i++)    {        Tree[i].clear();        g[i].clear();    }    memset(dp,0,sizeof(dp));}void build(int root){    /******************    题目给定的图是无根树,所以先把这个图转化为一颗以1为根的有根树,便于我们处理    ******************/    if(visit[root]) return;    visit[root] = true;    for(int i = 0; i < g[root].size(); i++)    {        int term = g[root][i];        if(!visit[term])        {            Tree[root].push_back(term);            build(term);        }    }}void dfs(int root){    if(Tree[root].size() == 0)//如果节点是叶节点的情况    {        for(int i = 1; i <= m; i++)        {            if(c[root][i]) dp[root][i] = 1;            else dp[root][i] = 0;        }        return;    }    for(int i = 0; i < Tree[root].size(); i++)//先处理子树    {        int son = Tree[root][i];        dfs(son);    }    for(int i = 1; i <= m; i++)    {        /*************************        分别计算出每一个dp[root][i],计算的方法为        1.若c[root][i] == 0,表示root点不能涂i颜色,所以dp[root][i] = 0.        2.若c[root][i] == 1,表示root点能涂i颜色,所以对于root的每一个儿子,我们        可以求出res = sum(dp[son][k]),其中k从1~m,但是k != i,因为相连的两点颜色不能相等        对于每一个儿子,求出的res累乘起来就行。所以dp[root][i] = mul(res[son]),son为root的所有儿子        *************************/        if(c[root][i])        {            ll sum = 1;            for(int j = 0; j < Tree[root].size(); j++)            {                ll res = 0;                int son = Tree[root][j];                for(int k = 1; k <= m; k++)                {                    if(k != i)                    res = (res + dp[son][k])%mod;                }                sum = (sum*(res%mod))%mod;            }            dp[root][i] = sum;        }        else dp[root][i] = 0;    }}int main(){    while(~scanf("%d%d",&n,&m))    {        init();        int u,v;        for(int i = 1; i <= n - 1; i++)        {            scanf("%d%d",&u,&v);            g[u].push_back(v);            g[v].push_back(u);        }        for(int i = 1; i <= n; i++)        {            for(int j = 1; j <= m; j++)            {                scanf("%d",&c[i][j]);            }        }        build(1);        dfs(1);        ll ans = 0;        /*****************        最后把所有的dp[1][i]加起来就行        *****************/        for(int i = 1; i <= m; i++)        {            ans = (ans + dp[1][i])%mod;        }        printf("%lld\n",ans%mod);    }    return 0;}/***********Create by lucky stars2017 4 10***********/
0 0
原创粉丝点击