Solution to a problem P3047 [USACO12FEB] cattle Nearby Cows nearby

Solution to a problem P3047 [USACO12FEB] cattle Nearby Cows nearby

Topic Link

Subject to the effect is to give you a tree, for each node i, obtains the right of the point within the range of k and

Look at the data to know the scope of violence certainly will t fly, so we have to consider how to dp (the code used to write dfs)

Think carefully about what we find point point i k-step walk to reach into the following two

1. In the subtree i (i down by a point)

2. After the father of i (i point from bottom to top)

This problem can generally be used twice dfs solve

We define the state of the F [i] [j] represents a j i point down the right of the point within the range of steps and, d [i] [j] denotes the point i walk up and down steps within a range of points j and Right.

First we determined all dfs f [n] [k], this is relatively simple, for its son nodes u and v, f [u] [k] + = f [v] [j - 1] on the line. (First known leaf node dfs push father node)

We d dfs second array has been determined to push the array f, for the son v u and u, d [v] [k] + = (d [u] [k - 1] - f [v] [k - 2]), under the table do not pay attention to the array bounds. d [i] [j] to be assigned to an initial value f [i] [j], as root d [i] [j] is f [i] [j]. (Second node dfs known father pushing his son node)

Ideas put it may be a bit wordyLook at the code it:

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#define ll long long
#define N 100005
using namespace std;
inline int read()
{
    int x = 0, f = 1;
    char c = getchar();
    while (c < '0' || c > '9') { if (c == '-') f = -1; c = getchar(); }
    while (c >= '0' && c <= '9') { x = x * 10 + c - '0'; c = getchar(); }
    return x * f;
}

ll f[N][25], d[N][25];
//f数组和d数组前面已经说了
int val[N];
int n, k, tot, head[N];

struct edge
{
    int to, next;
    edge() {}
    edge(int x, int y) { to = x; next = y; }
}a[N * 2];
//邻接表存图
void add(int from, int to)
{
    a[++tot] = edge(to, head[from]);
    head[from] = tot;
}

void dfs(int x, int fa)
{
    for (int i = 0; i <= k; i++) f[x][i] = val[x];
    for (int i = head[x]; i; i = a[i].next)
    {
        int u = a[i].to;
        if (u != fa)
        {
            dfs(u, x);//先dfs到叶子节点,然后推父亲节点
            for (int i = 1; i <= k; i++)
                f[x][i] += f[u][i - 1];
        }
    }
}
//第一次dfs
void dfs2(int x, int fa)
{
    for (int i = head[x]; i; i = a[i].next)
    {
        int u = a[i].to;
        if (u != fa)
        {
            d[u][1] += f[x][0];
            for (int i = 2; i <= k; i++)
                d[u][i] += d[x][i - 1] - f[u][i - 2];
            dfs2(u, x);//先dfs父亲节点,更新完儿子后dfs儿子
        }
    }
}
//第二次dfs
int main()
{
    n = read(), k = read();
    for (int i = 1; i < n; i++)
    {
        int a1 = read(), a2 = read();
        add(a1, a2);
        add(a2, a1);
    }
    for (int i = 1; i <= n; i++)
        val[i] = read();
    dfs(1, 1);
    for (int i = 1; i <= n; i++)
        for (int j = 0; j <= k; j++)
            d[i][j] = f[i][j];//把f赋给d
    dfs2(1, 1);
    for (int i = 1; i <= n; i++)
        cout << d[i][k] << endl;//输出答案
    return 0;
}

Anyway, I have a kind of tree dp question, the answer to this node of each node father and son are related, this time we can find the answer in two dfs, dfs facilitate these two different general order. This requires you to traverse the tree has a very deep understanding and ability to achieve, but the idea is actually not so difficult.

19.08.31

Guess you like

Origin www.cnblogs.com/YuanqiQHFZ/p/11622361.html