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

posted @ 2025-10-14 21:21  bz02_2023f2  阅读(10)  评论(0)    收藏  举报  来源