HDU 5927 Auxiliary Set By Assassin
来源:互联网 发布:js点击radio 编辑:程序博客网 时间:2024/06/05 14:12
Problem Description
Given a rooted tree with n vertices, some of the vertices are important.
An auxiliary set is a set containing vertices satisfying at least one of the two conditions:
∙
It is an important vertex
∙
It is the least common ancestor of two different important vertices.
You are given a tree with n vertices (1 is the root) and q queries.
Each query is a set of nodes which indicates the unimportant vertices in the tree. Answer the size (i.e. number of vertices) of the auxiliary set for each query.
Input
The first line contains only one integer T (
T≤1000
), which indicates the number of test cases.
For each test case, the first line contains two integers n (
1≤n≤100000
), q (
0≤q≤100000
).
In the following n -1 lines, the i-th line contains two integers
u
i
,
v
i
(1≤
u
i
,
v
i
≤n)
indicating there is an edge between
u
i
i and
v
i
in the tree.
In the next q lines, the i-th line first comes with an integer
m
i
(1≤
m
i
≤100000)
indicating the number of vertices in the query set.Then comes with mi different integers, indicating the nodes in the query set.
It is guaranteed that
∑
q
i=1
m
i
≤100000
.
It is also guaranteed that the number of test cases in which
n≥1000
or
∑
q
i=1
m
i
≥1000
is no more than 10.
Output
For each test case, first output one line “Case #x:”, where x is the case number (starting from 1).
Then q lines follow, i-th line contains an integer indicating the size of the auxiliary set for each query.
Sample Input
1
6 3
6 4
2 5
5 4
1 5
5 3
3 1 2 3
1 5
3 3 1 4
Sample Output
Case #1:
3
6
3
这个题目本来以为时LCA,但是LCA还没学会,就被告诉xjb可以出来。。。
题意:题目大概是这样的,一颗树一种叫Auxiliary Set节点,如果满足该点是重要的或者是某两点的 least common ancestor 就满足条件。但是这个可以用类似贪心的方法做。我们首先将树建立好,用father数组和son数组分别纪录i点的父亲和孩子是谁,dep数组纪录数的层数。
那么我们如何判断一个点是否为LCA呢?只要他有至少两个子树中分别有重要点就行。那么怎么办!树状dp?NO!会超时!我们用dep层数从底层到高层排序!酱紫!
int cmp(const int &aa,const int &bb){ if(dep[aa]>dep[bb])return 1; return 0;}
好了,每次从底层对上层的影响是什么?如果时叶子结点,son[i]==0,那么son[father[i]]就减一!如果father这个点值还是不小与2!可以了!
当然,这里我们还需要!注意!这里每次赋值要每次直接用输入的值,专业点处离散化
#include<bits/stdc++.h>#define input freopen("input.txt","r",stdin)using namespace std;vector<int>s[100005];int father[100005],son[100005],a[100005],dep[100005],cha[100005];void dfs(int u,int pa) { father[u]=pa; dep[u]=dep[pa]+1; son[u]=0; for(int i=0; i<s[u].size(); i++) if(s[u][i]!=pa) { dfs(s[u][i],u); son[u]++; }}int cmp(const int &aa,const int &bb){ if(dep[aa]>dep[bb])return 1; return 0;}int main(){ input; int i,j; int q,n,m,tmp1,tmp2; int t,time=1; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&q); for(i=0;i<=n;i++) s[i].clear(); for(i=1;i<n;i++) { scanf("%d%d",&tmp1,&tmp2); s[tmp1].push_back(tmp2); s[tmp2].push_back(tmp1); } dfs(1,0);// for(i=1;i<=n;i++)cout<<son[i]<<" ";cout<<endl; printf("Case #%d:\n",time++); while(q--) { scanf("%d",&m); int ans=n-m; for(i=1;i<=m;i++) scanf("%d",&a[i]); for(i=1;i<=m;i++) cha[a[i]]=son[a[i]]; sort(a+1,a+1+m,cmp); for(i=1;i<=m;i++) { if(cha[a[i]]>=2)ans++; else if(cha[a[i]]==0) cha[father[a[i]]]--; } cout<<ans<<endl; } } return 0;}
PS:其实时借鉴大牛思路!感谢!
- HDU 5927 Auxiliary Set By Assassin
- hdu 5927 Auxiliary Set
- hdu 5927 Auxiliary Set
- HDU 5927 Auxiliary Set
- HDU 5927Auxiliary Set
- hdu 5927 Auxiliary Set dfs
- F - Auxiliary Set HDU - 5927
- hdu 5927 Auxiliary Set (dfs)
- hdu 5927 Auxiliary Set (分析*)
- HDU 5927 Auxiliary Set dfs(思维)
- HDU - 5927 Auxiliary Set (树形DP)
- HDU 5927 Auxiliary Set DFS好题
- HDU 5927 Auxiliary Set(DFS)
- hdu 5927 Auxiliary Set(思路)
- HDU 5927 Auxiliary Set 最近公共祖先
- HDU 5927 Auxiliary Set (DFS+模拟)
- hdu 5927 Auxiliary Set dfs+逆向思维
- HDU 5927 Auxiliary Set (树形)
- HDU5927
- MD5加密
- mingw 编译openvpn 编译tap-win32时报错
- 面试技巧
- linux文件1
- HDU 5927 Auxiliary Set By Assassin
- JSTL标签库之核心标签
- 【计划】国庆总结及近期计划
- 欢迎使用CSDN-markdown编辑器
- object c 代理设计模式,有点像java的监听
- Java开发中的23种设计模式总结
- HTML个人学习总结—2
- 116. Populating Next Right Pointers in Each Node
- unity 背包Item拖拉