武大校赛网络赛B题

B. Color

链接:武大校赛网络赛B题
题意是给定一棵树然后每个节点可以染色,总共有m种颜色,给出一个01矩阵代表第i个点是否能染第j种颜色,然后问总共有多少种染色方法。
很明显的树形dp,可是比赛的时候没有时间去做,真的很可惜,
dp[u][i]为第u个点染第i种颜色的方案数
dp[u][i] = dp[u][i] * ∑dp[v][j] (i != j && v为u的son)

这次比赛很不顺利,6个题都是知道怎么做的可是只写出2个来真的很难受。
总结起来还是太菜,之前沉迷蓝桥杯不能自已,训练的题目太少了,这次dp专场也没发挥出自己的水平来,太难受了。
#include<cmath>
#include<algorithm>
#include<cstring>
#include<string>
#include<set>
#include<map>
#include<time.h>
#include<cstdio>
#include<vector>
#include<stack>
#include<queue>
#include<iostream>
using namespace std;
#define  LONG long long
const LONG   INF=0x3f3f3f3f3f3f;
const LONG MOD=1e7+9;
const double PI=acos(-1.0);
#define clrI(x) memset(x,-1,sizeof(x))
#define clr0(x) memset(x,0,sizeof x)
#define clr1(x) memset(x,INF,sizeof x)
#define clr2(x) memset(x,-INF,sizeof x)
#define EPS 1e-10
#define root 1 , n , 1
#define lson  l , mid , rt<< 1
#define rson  mid + 1 ,r , (rt<<1)+1
struct Edge
{
    LONG to , u , next ;
}edge[22000];
LONG head[12000];
LONG tot = 0;
LONG n , m;
LONG dp[22000][30] ;
LONG Map[22000][30] ;
void Add(LONG u , LONG v )
{

    edge[++tot].to = v;
    edge[tot].u = u ;
    edge[tot].next = head[u] ;
    head[u] = tot ;
}
void Init()
{
    clrI(head) ;
    tot = 0 ;
    clr0(dp) ;

}
void dfs(LONG pre , LONG u )
{
    LONG t = 0;
    for( int  i = 1; i<= m ;++ i) if(Map[u][i])dp[u][i] = 1;
    for( LONG i = head[u] ; i != -1 ; i = edge[i].next)
    {
        LONG v = edge[i].to ;
        if(v == pre) continue ;
        dfs(u, v) ;
        for(LONG j = 1 ; j <= m ; ++ j)
        {
            if(!Map[u][j]) continue ;
            LONG res = 0;
            for(LONG k = 1; k<= m ;++ k)
            {
            if(j == k ) continue ;


                res = (res + dp[v][k] ) % MOD ;

            }
            dp[u][j] = (dp[u][j] *res ) % MOD ;
        }
        t ++ ;
    }
}
int  main()
{

    while(~scanf("%lld%lld",&n,&m))
    {
        Init() ;
        LONG u ,v ;
        for(LONG i = 1; i< n ;++ i)
        {
            scanf("%lld%lld",&u,&v) ;
            Add(u , v) ;
            Add(v ,  u ) ;
        }
        for(LONG i =1 ; i<= n ;++ i)
        {
            for( LONG j = 1 ; j<= m ; ++ j)
                scanf("%lld" , &Map[i][j]) ;
        }

        for(LONG j = 1; j <= m ;++ j)
            if(Map[1][j])
                dp[1][j] = 1;
        dfs(-1 , 1) ;
        LONG ans = 0 ;
        for(int i = 1; i <= m ;++ i)ans = (ans + dp[1][i] ) %MOD ;
        cout<<ans<<endl;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值