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;
}
}