P4084 [USACO17DEC]Barn Painting

题意翻译

题意:给定一颗N个节点组成的树,3种颜色,其中K个节点已染色,要求任意两相邻节点颜色不同,求合法染色方案数。 翻译贡献者:Il_ItzABC_lI

题目描述

Farmer John has a large farm with NN barns (1 \le N \le 10^51N105), some of which are already painted and some not yet painted. Farmer John wants to paint these remaining barns so that all the barns are painted, but he only has three paint colors available. Moreover, his prize cow Bessie becomes confused if two barns that are directly reachable from one another are the same color, so he wants to make sure this situation does not happen.

It is guaranteed that the connections between the NN barns do not form any 'cycles'. That is, between any two barns, there is at most one sequence of connections that will lead from one to the other.

How many ways can Farmer John paint the remaining yet-uncolored barns?

输入格式

The first line contains two integers NN and KK (0 \le K \le N0KN), respectively the number of barns on the farm and the number of barns that have already been painted.

The next N-1N1 lines each contain two integers xx and yy (1 \le x, y \le N, x \neq y1x,yN,xy) describing a path directly connecting barns xx and yy.

The next KK lines each contain two integers bb and cc (1 \le b \le N1bN, 1 \le c \le 31c3) indicating that barn bbis painted with color cc.

输出格式

Compute the number of valid ways to paint the remaining barns, modulo 10^9 + 7109+7, such that no two barns which are directly connected are the same color.

输入输出样例

输入 #1
4 1
1 2
1 3
1 4
4 3
输出 #1
8


#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<queue>
#define p 1000000007
#define LL long long
using namespace std;
inline int read()
{
    int sum=0;
    char ch =getchar();
    while(ch<'0'||ch>'9')
        ch=getchar();
    while(ch>='0'&&ch<='9')
    {
        sum=sum*10+ch-'0';
        ch=getchar();
    }
    return sum;
}
int n,m,tot=0;
int Head[100005],col[100005];//Head用于邻接表  col记录颜色
LL dp[100005][4];
bool visit[100005];//由于存图为无向图,所以要记录下已经走过的点防止死循环
struct tree
{
    int next,node;
}h[200010];
inline void add(int u,int v)//邻接表存图
{
    h[++tot].next=Head[u];
    h[tot].node=v;
    Head[u]=tot;
}
void dfs(int pos)//dfs遍历
{
    visit[pos]=1;
    if(col[pos])//如果已经上过色了,其他两种颜色的方案数为0。
        dp[pos][col[pos]]=1;
    else//三种颜色都可以被♂上
    {
        dp[pos][1]=1;
        dp[pos][2]=1;
        dp[pos][3]=1;
    }
    for(register int i=Head[pos];i;i=h[i].next)//找到当前点所有的子节点
    {
        int v=h[i].node;
        if(!visit[v])
        {
            dfs(v);//一直向下遍历直到叶子节点返回
            dp[pos][1]=dp[pos][1]*((dp[v][2]+dp[v][3])%p)%p;
            dp[pos][2]=dp[pos][2]*((dp[v][1]+dp[v][3])%p)%p;
            dp[pos][3]=dp[pos][3]*((dp[v][2]+dp[v][1])%p)%p;//转移  记得取模!
        }
    }
}
int main()
{
    int x,y;
    n=read();
    m=read();
    for(register int i=1;i<n;++i)
    {
        x=read();
        y=read();
        add(x,y);
        add(y,x);//加边
    }
    for(register int i=1;i<=m;++i)
    {
        x=read();
        y=read();
        col[x]=y;//记录颜色
    }
    dfs(1);//随便把一个点当根就好了
    cout<<(dp[1][1]+dp[1][2]+dp[1][3])%p<<endl;
    return 0;
}

  

猜你喜欢

转载自www.cnblogs.com/xiongchongwen/p/11243553.html