码迷,mamicode.com
首页 > 其他好文 > 详细

【2016东北四省赛】

时间:2016-10-26 00:17:49      阅读:185      评论:0      收藏:0      [点我收藏+]

标签:color   clear   题解   can   统计   include   东北   case   back   

HDU5927

题意:给出一个根节点为1的树(n <= 100000),树中的结点分为重要结点与不重要结点。

有q个询问,每次询问给出一个不重要结点的集合(m <= 100000), 统计一类点(它是重要结点 或者 它是两个重要结点的最近公共祖先) 的总数。

题解:维护一个set集合表示以该结点为根的子树不含重要结点,set集合初始即为m个点。按 后序遍历 将集合中的点排序后(ra表示结点后序遍历中的排名),对每个点,查找子结点点,若至少有两个子结点不在set里,则该点是可行点,同时将其从集合中删除。

复杂度分析:每次询问的复杂度为O(mlogm)

time: 1794MS

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 const int N = 1e5+10;
 4 vector<int> ve[N];
 5 int ra[N], tot;
 6 void dfs(int f, int x){
 7     for(int i = 0; i < ve[x].size(); i++){
 8         int y = ve[x][i];
 9         if(y == f) continue ;
10         dfs(x, y);
11     }
12     ra[x] = tot++;
13 }
14 bool cmp(int a, int b){
15     return ra[a] < ra[b];
16 }
17 
18 
19 int temp[N];
20 int tag[N];
21 int main(){
22     int t, ca = 1; scanf("%d", &t);
23     while(t--){
24         int n, q, u, v; scanf("%d%d", &n, &q);
25         for(int i = 1; i < n; i++){
26             scanf("%d%d", &u, &v);
27             ve[u].push_back(v);
28             ve[v].push_back(u);
29         }
30         tot = 0;
31         dfs(0, 1);
32         printf("Case #%d:\n", ca++);
33         while(q--){
34             int m, x; scanf("%d", &m);
35             for(int i = 0; i < m; i++)
36                 scanf("%d", temp+i);
37             sort(temp, temp+m, cmp);
38             set<int> se;
39             for(int i = 0; i < m; i++)
40                 se.insert(temp[i]);
41             int ans = 0;
42             for(int i = 0; i < m; i++){
43                 int x = temp[i], sum = 0;
44                 for(int j = 0; j < ve[x].size(); j++){
45                     int y = ve[x][j];
46                     if(ra[y] > ra[x]) continue;
47                     if(se.find(y) == se.end()){
48                         sum++;
49                         if(sum > 1){
50                             ans++;
51                             break;
52                         }
53                         se.erase(x);
54                     }
55                 }
56             }
57             printf("%d\n", n-m+ans);
58         }
59         for(int i = 1; i <= n; i++)
60             ve[i].clear();
61     }
62     return 0;
63 }

 

【2016东北四省赛】

标签:color   clear   题解   can   统计   include   东北   case   back   

原文地址:http://www.cnblogs.com/dirge/p/5998729.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!