标签:
题意:
给一棵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:\n",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\n",ans+n-nn); 63 } 64 } 65 return 0; 66 }
标签:
原文地址:http://www.cnblogs.com/bin-gege/p/5935104.html