[USACO17DEC] Barn Painting G题解
题目描述
Farmer John 有一个大农场,农场上有 N 个谷仓(1≤N≤105),其中一些已经涂色,另一些尚未涂色。Farmer John 想要为这些剩余的谷仓涂色,使得所有谷仓都被涂色,但他只有三种可用的油漆颜色。此外,他的获奖奶牛 Bessie 如果发现两个直接相连的谷仓颜色相同,会感到困惑,因此他希望确保这种情况不会发生。
保证 N 个谷仓之间的连接不会形成任何“环”。也就是说,任意两个谷仓之间最多只有一条连接路径。
Farmer John 有多少种方式可以为剩余的未涂色谷仓涂色?
输入格式
第一行包含两个整数 N 和 K(0≤K≤N),分别表示农场上的谷仓数量和已经涂色的谷仓数量。
接下来的 N−1 行每行包含两个整数 x 和 y(1≤x,y≤N,x=y),描述直接连接谷仓 x 和 y 的路径。
接下来的 K 行每行包含两个整数 b 和 c(1≤b≤N, 1≤c≤3),表示谷仓 b 已经被涂成颜色 c。
输出格式
计算为剩余谷仓涂色的有效方式数量,模 109+7,要求任何两个直接相连的谷仓颜色不同。
显示翻译
题意翻译
输入输出样例
输入 #1复制
4 1 1 2 1 3 1 4 4 3
输出 #1复制
8
思路
DP
代码见下
#include<bits/stdc++.h>
using namespace std;
long long n,k,x,y,a[100005],b,c,f[100005][4],mod=1e9+7;
vector<long long> v[100005];
bool bo[100005];
void abc(long long a1,long long fa){
if(bo[a1]==0){
if(a[a1]==0){
f[a1][1]=f[a1][2]=f[a1][3]=1;
}
else{
f[a1][a[a1]]=1;
}
return ;
}
if(a[a1]==0){
f[a1][1]=f[a1][2]=f[a1][3]=1;
for(int i=0;i<v[a1].size();i++){
long long tt=v[a1][i];
if(tt!=fa){
abc(tt,a1);
f[a1][1]*=(f[tt][2]+f[tt][3]);
f[a1][2]*=(f[tt][1]+f[tt][3]);
f[a1][3]*=(f[tt][1]+f[tt][2]);
f[a1][1]%=mod;
f[a1][2]%=mod;
f[a1][3]%=mod;
}
}
}
else{
f[a1][a[a1]]=1;
for(int i=0;i<v[a1].size();i++){
long long tt=v[a1][i];
if(tt!=fa){
abc(tt,a1);
f[a1][1]*=(f[tt][2]+f[tt][3]);
f[a1][2]*=(f[tt][1]+f[tt][3]);
f[a1][3]*=(f[tt][1]+f[tt][2]);
f[a1][1]%=mod;
f[a1][2]%=mod;
f[a1][3]%=mod;
}
}
}
return ;
}
void abc2(long long a1,long long fa){
for(int i=0;i<v[a1].size();i++){
long long tt=v[a1][i];
if(tt!=fa){
bo[a1]=1;
abc2(tt,a1);
}
}
}
int main(){
cin>>n>>k;
for(int i=1;i<=n-1;i++){
cin>>x>>y;
v[x].push_back(y);
v[y].push_back(x);
}
for(int i=1;i<=k;i++){
cin>>b>>c;
a[b]=c;
}
abc2(1,0);
abc(1,0);
cout<<(f[1][1]+f[1][2]+f[1][3])%mod<<endl;
return 0;
}

浙公网安备 33010602011771号