目录

P6626-[省选联考 2020 B 卷] 消息传递

P6626-[省选联考 2020 B 卷] 消息传递

题目:

题目描述:

给定一个包含 $n$ 个人(从 $1$ 到 $n$ 编号)的树形社交网络。如果一个人在某天收到了一条消息,则下一天他会将消息传递给所有与他有直接社交关系的人。

现在有 $m$ 次询问,每次询问假定第 $0$ 天 $x$ 号人收到了一条消息,请你计算第 $k$ 天时新收到此条消息的人数(即第 $k$ 天前收到过此条消息的人不计入其中)。不同询问间互不影响。

输入格式:

本题包含多组测试数据。

第一行一个整数 $T$,为测试数据组数。

对于每组测试数据:

第一行两个数 $n,m$ 分别表示树形社交网络的人数和询问的数量。

接下来 $n - 1$ 行,每行两个数 $a, b$,表示 $a$ 号人和 $b$ 号人之间有直接社交关系。保证输入的是树形社交网络。

接下来 $m$ 行,每行两个数 $x, k$,意义见题目描述。

输出格式:

对于每组测试数据:输出 $m$ 行,每行一个数表示询问的答案。

样例:

样例输入1:

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

样例输出1:

1
2
1
1

思路:

实现:

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
#include "ybwhead/ios.h"
int n, m;
const int maxn = 1e5 + 10;
int head[maxn], tot;
struct edge
{
    int v, nxt;
} e[maxn << 1];
void __ADD(int u, int v)
{
    e[++tot].v = v;
    e[tot].nxt = head[u];
    head[u] = tot;
}
void add(int u, int v)
{
    __ADD(u, v);
    __ADD(v, u);
}
int pos, tmp;
int w[maxn], v[maxn];
int dep[maxn], sz[maxn], c[maxn];
vector<pair<int, int>> q[maxn];
int ans[maxn];

int sum;
int siz[maxn];
int ms[maxn];
int rt;
int vis[maxn];
void gr(int u, int fa)
{
    // cout << u << endl;
    siz[u] = ms[u] = 1;
    for (int i = head[u]; i; i = e[i].nxt)
    {
        int v = e[i].v;
        if (v != fa && !vis[v])
        {
            gr(v, u);
            siz[u] += siz[v];
            if (siz[v] > ms[u])
                ms[u] = siz[v];
        }
    }
    ms[u] = max(ms[u], sum - siz[u]);
    if (ms[u] < ms[rt])
        rt = u;
}
int xp[maxn];
void getdep(int u, int fa)
{
    // cout << u << endl;
    ++xp[dep[u]];
    for (int i = head[u]; i; i = e[i].nxt)
    {
        int v = e[i].v;
        if (vis[v] || v == fa)
            continue;
        dep[v] = dep[u] + 1;
        getdep(v, u);
    }
}
void remove(int u, int fa, int d)
{
    xp[dep[u]] += d;
    for (int i = head[u]; i; i = e[i].nxt)
    {
        int v = e[i].v;
        if (v != fa && !vis[v])
        {
            remove(v, u, d);
        }
    }
}
void getans(int u, int fa)
{
    // cout << u << endl;
    for (int i = 0; i < q[u].size(); ++i)
    {
        int k = q[u][i].first - dep[u];
        if (k < 0)
            continue;
        ans[q[u][i].second] += xp[k];
    }
    for (int i = head[u]; i; i = e[i].nxt)
    {
        int v = e[i].v;
        if (v == fa || vis[v])
            continue;
        getans(v, u);
    }
}

void ga(int u)
{
    // cout << u << endl;
    int mxd = 0;
    dep[u] = 0;
    getdep(u, 0);
    for (int i = 0; i < q[u].size(); i++)
    {
        int k = q[u][i].first;
        ans[q[u][i].second] += xp[k];
    }
    for (int i = head[u]; i; i = e[i].nxt)
    {
        int v = e[i].v;
        if (!vis[v])
        {
            remove(v, u, -1);
            getans(v, u);
            remove(v, u, 1);
        }
    }
    remove(u, 0, -1);
}
void solve(int u)
{
    vis[u] = 1;
    ga(u);
    for (int i = head[u]; i; i = e[i].nxt)
    {
        int v = e[i].v;
        if (vis[v])
            continue;
        rt = 0;
        ms[0] = INT_MAX;
        sum = siz[v];
        gr(v, u);
        solve(rt);
    }
}
void clear()
{
    memset(head, 0, sizeof(head));
    tot = 0;
    memset(ans, 0, sizeof(ans));
    memset(vis, 0, sizeof(vis));
    for (int i = 1; i <= n; ++i)
    {
        q[i].clear();
    }
}
int main()
{
    int TTT;
    yin >> TTT;
    while (TTT--)
    {
        clear();
        yin >> n >> m;
        for (int i = 1; i < n; i++)
        {
            int a, b;
            yin >> a >> b;
            add(a, b);
        }
        for (int i = 1; i <= m; i++)
        {
            int x, y;
            yin >> x >> y;
            q[x].push_back(make_pair(y, i));
        }
        sum = n;
        ms[0] = INT_MAX;
        gr(1, 0);
        solve(rt);
        for (int i = 1; i <= m; i++)
        {
            yout << ans[i] << endl;
        }
    }
    return 0;
}