HDU-5927 Auxiliary Set

先预处理出每个节点的父节点,子节点个数,深度

当一个不重要节点有两个或以上子节点,并且有两个或以上子树里有重要点,那么它也会变为重要点

对于每次询问先把不重要点按深度排序,然后按顺序看其是否满足以上条件

需要加一个数组保存节点有多少子树有重要点

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 1e5 + 10;
struct Edge
{
    int to, nxt;
} edge[2 * N];
int tot, tot0;
int first[N], first0[N];
void addedge(int u, int v)
{
    edge[tot].to = v;
    edge[tot].nxt = first[u];
    first[u] = tot++;
}
int deep[N], f[N], son[N];
void init(int u, int d, int fa)
{
    deep[u] = d;
    son[u] = 0;
    f[u] = fa;
    for (int i = first[u]; i != -1; i = edge[i].nxt)
    {
        int v = edge[i].to;
        if (v != fa)
        {
            init(v, d + 1, u);
            son[u]++;
        }
    }
}
bool cmp(int a, int b)
{
    return deep[a] > deep[b];
}
int vv[N];
int num[N];
int ans;
int main()
{
    int T, kase = 0;
    scanf("%d", &T);
    while (T--)
    {
        int n, q;
        scanf("%d%d", &n, &q);
        int a, b;
        tot = 0;
        memset(first, -1, sizeof(int) * (n + 1));
        for (int i = 0; i < n - 1; i++)
        {
            scanf("%d%d", &a, &b);
            addedge(a, b);
            addedge(b, a);
        }
        printf("Case #%d:\n", ++kase);
        if (!q)
            continue;
        init(1, 0, 1);
        int m;
        memset(vv, 0, sizeof(int) * (n + 1));
        while (q--)
        {
            scanf("%d", &m);
            for (int i = 0; i < m; i++)
            {
                scanf("%d", &num[i]);
                vv[num[i]] = 0;
            }
            sort(num, num + m, cmp);
            ans = n - m;
            for (int i = 0; i < m; i++)
            {
                if (son[num[i]] - vv[num[i]] >= 2)
                    ans++;
                else if (son[num[i]] - vv[num[i]] == 0)
                    vv[f[num[i]]]++;
            }
            printf("%d\n", ans);
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/wl16wzl/article/details/82935995