您的位置:首页 > 其它

HDU 5927 Auxiliary Set dfs(思维)

2016-10-07 14:21 330 查看

题目:

http://acm.hdu.edu.cn/showproblem.php?pid=5927

题意:

有一棵n个节点的有根树(1为树根),先定义重要节点x如下:1.x是重要节点。2.x的两个重要节点的lca。每次询问给出m个不重要节点(意味着其余点都是重要节点),问当前树中有重要节点的个数。

思路:

本题其实是求不重要节点中有多少节点可以变成重要节点。首先对树进行一次dfs,求出每个节点的父亲和儿子的个数,以及其深度,然后对于m个不重要节点,按深度从大到小排序,然后依次判断:对于当前点,如果它的儿子数量大于等于2,那么当前点一定是一个重要节点,如果儿子数量等于1,那么关系到当前点的祖先节点是不是重要节点,不处理,如果等于0,那么当前点肯定不是重要节点,同时其父亲节点的儿子数量减1

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <cmath>
using namespace std;

const int N = 100100;
struct edge
{
int to, next;
}g[N*2];
int cnt, head
;
int son
, par
, d
, dep
, tmp
;
bool vis
;
int n, m, cas;
void add_edge(int v, int u)
{
g[cnt].to = u, g[cnt].next = head[v], head[v] = cnt++;
}
void dfs(int v, int fa, int d)
{
vis[v] = true, par[v] = fa, dep[v] = d;
for(int i = head[v]; i != -1; i = g[i].next)
{
int u = g[i].to;
if(! vis[u]) dfs(u, v, d + 1), son[v]++;
}
}
bool cmp(int a, int b)
{
return dep[a] > dep[b];
}
int main()
{
int t;
scanf("%d", &t);
while(t--)
{
scanf("%d%d", &n, &m);
cnt = 0;
for(int i = 1; i <= n; i++) head[i] = -1, son[i] = 0, vis[i] = false;
int v, u;
for(int i = 1; i <= n - 1; i++)
{
scanf("%d%d", &v, &u);
add_edge(v, u), add_edge(u, v);
}
dfs(1, -1, 1);
printf("Case #%d:\n", ++cas);
for(int i = 1; i <= m; i++)
{
int k;
scanf("%d", &k);
int ans = n - k;
for(int j = 1; j <= k; j++) scanf("%d", &d[j]);
for(int j = 1; j <= k; j++) tmp[d[j]] = son[d[j]];
sort(d+1, d+1+k, cmp);
for(int j = 1; j <= k; j++)
if(tmp[d[j]] >= 2) ans++;
else if(tmp[d[j]] == 0) tmp[par[d[j]]]--;
printf("%d\n", ans);
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: