hdu_5927_Auxiliary Set(xjb搞)

题目链接:hdu_5927_Auxiliary Set

题意:

给一棵n个节点的树,最开始全部都是重点,现在有q个询问,每次给你一些轻点,并叫你输出整棵树的重点数量,

轻点可能会变为重点,如果这个轻点是两个重点的lca。

题解:

这里 我把有重点的子树叫重子树,一个重点都没有的子树叫轻子树。

一个轻点如果有两个重子树,那么这个轻点就会变为重点,可以画图试试。

然后我们就将轻点从树的最底层开始更新

x为这个点的子树个数,n为这个点的轻子树个数,

如果x-n=0,那么这个点的父亲节点的n就++

如果x-n<=1那么这个点就不能变会重点

最后统计一下轻点变回重点的个数

 1 #include<bits/stdc++.h>
 2 #define F(i,a,b) for(int i=a;i<=b;++i)
 3 using namespace std;
 4 
 5 const int N=1e5+7;
 6 int ic=1,t,n,q;
 7 int g[N],v[N*2],nxt[N*2],ed,dfs_idx,hsh[N];
 8 
 9 struct node
10 {
11     int in,pre,n,x,col,idx;
12     bool operator < (const node &b)const{return in>b.in;}
13 }nd[N],tmp[N];
14 
15 inline void adg(int x,int y){v[++ed]=y,nxt[ed]=g[x],g[x]=ed;}
16 
17 void init()
18 {
19     memset(g,0,sizeof(g));
20     ed=0,dfs_idx=0;
21 }
22 
23 void dfs(int u=1,int pre=0)
24 {
25     nd[u].idx=u,nd[u].in=++dfs_idx,nd[u].pre=pre;
26     nd[u].col=1,nd[u].n=0,nd[u].x=0;
27     for(int i=g[u];i;i=nxt[i])if(v[i]!=pre)nd[u].x++,dfs(v[i],u);
28 }
29 
30 int main(){
31     scanf("%d",&t);
32     while(t--)
33     {
34         printf("Case #%d:
",ic++);
35         init();
36         scanf("%d%d",&n,&q);
37         F(i,1,n-1)
38         {
39             int x,y;
40             scanf("%d%d",&x,&y);
41             adg(x,y),adg(y,x);
42         }
43         dfs();
44         F(i,1,q)
45         {
46             int nn,x;
47             int ans=0;
48             scanf("%d",&nn);
49             F(j,1,nn)scanf("%d",&x),tmp[j]=nd[x];
50             sort(tmp+1,tmp+1+nn);
51             F(j,1,nn)hsh[tmp[j].idx]=j;
52             F(j,1,nn)
53             {
54                 if(tmp[j].x-tmp[j].n<2)tmp[j].col=0;
55                 if(tmp[j].x-tmp[j].n==0)tmp[hsh[nd[tmp[j].idx].pre]].n++;
56             }
57             F(j,1,nn)
58             {
59                 if(tmp[j].col==1)ans++;
60                 hsh[tmp[j].idx]=0;
61             }
62             printf("%d
",ans+n-nn);
63         }
64     }
65     return 0;
66 }
View Code
原文地址:https://www.cnblogs.com/bin-gege/p/5935104.html