sheep and sheep---dfs递推

任意门
Nowadays Wayne is playing a game named ‘Sheep and Sheep’. In this game you can choose several items to hold in your hand, and when you have three items with the same icon in your hand these three items will be eliminated, and you will get one score. Only after you selecting the top item, you can select the item that is covered by this item.

We can simplify the placement of these items as a tree with 1 as the root. It means the child vertex can be selected only after you have selected the parent vertex.

Each vertex has an icon, which we represent it by a number colori.

Assume that in one round the placement of all items can be represented by a subtreei with vi as the root. Can you tell Wayne how many scores he can get in this round?

To simplify the problem, we can assume that he can hold countless cards in his hand, which means every time he gets three items with the same coin he can get one point, no matter how many items with other icons there are between those three cards.

What’s more, the game does not guarantee that you will eventually be able to eliminate all items.

Input
The first line contains three integers N,M,K(1≤N,M≤1000,1≤K≤15), means there are N vertexes in the tree. You need to answer the question for M times and there are K types of icons.

The second line contains N integers colori,(1≤colori≤K), colori represents the color of the i−th vertex.

Then there are n−1 lines contains two integers ai,bi(1≤ai,bi≤N) represents the edge of the tree with 1 as the root.

The last M lines each line contains an integer Qi, represents the i−th query.

Output
For each query, output a single line with an integer.

input

6 6 1
1 1 1 1 1 1
1 3
3 6
2 3
5 6
2 4
1
2
3
4
5
6

output

2
0
1
0
0
0

#include <bits/stdc++.h>

using namespace std;

const int N = 4e3+10, K = 20;
int f[N][K];
int n, m, k;
int h[N], e[N], ne[N], idx;
int color[N];

void add(int a, int b)
{
    e[idx] = b;
    ne[idx] = h[a];
    h[a] = idx++;
}

void dfs(int t, int fa)
{
    f[t][color[t]] = 1;
    for(int i = h[t]; i != -1; i = ne[i])
    {
        int j = e[i];
        if(j != fa){
            dfs(j, t);
            for(int q = 1; q <= k; q++)
                f[t][q] += f[j][q];
        }
    }

}

int main(){
    memset(h, -1, sizeof h);
    scanf("%d%d%d", &n, &m, &k);
    for(int i  = 1; i <= n; i++) scanf("%d", &color[i]);
    for(int i = 1; i < n; i++)
    {
        int a, b;
        scanf("%d%d", &a, &b);
        add(a, b);
        add(b, a);
    }
    dfs(1, -1);
    while(m--){
        int x;
        scanf("%d", &x);
        int ans = 0;
        for(int i = 1; i <= k; i++) ans += f[x][i]/3;
        printf("%d\n", ans);
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值