HDU 5927 Auxiliary Set (dfs+lca)
阿新 • • 發佈:2018-12-14
題意:
給出一個樹,和一個點集,點集外的點為“重要的點”,如果某個點集內的點是兩個“重要的點的LCA”,那麼它也是“重要的點”,其他點為“非重要的點”。 求出重要的點的個數。
分析:
其實對於每一個詢問我們只要判斷哪些不重要的點是能進入集合的,那麼對於一個不重要的點x,怎樣才能進入集合呢?我們先dfs對於所有的點求出fa[x]和son[x]。當詢問是,我們先初始確定每個不重要的點的son'[x],如果一個點要進入集合那麼顯然要求son'[x]>=2,這樣才會有兩個重要的點的最近公共祖先是x。那麼對於一個點x的son'又會受什麼影響呢?當一個點y滿足son'[y]==0&&y是不重要的點那麼son'[fa[y]]--。這樣我們就能維護我們需要的資訊了。O(mlogm)
#include<bits/stdc++.h> using namespace std; const int maxn=2e5+10; int dep[maxn]; int fa[maxn]; int son[maxn]; int son_[maxn]; int d[maxn]; int head[maxn]; int tot; struct node{ int to; int next; }g[maxn]; void addedge(int u,int v){ g[tot].to=v; g[tot].next=head[u]; head[u]=tot++; } void dfs(int v,int pre){ fa[v]=pre; dep[v]=dep[pre]+1; son[v]=0; for(int i=head[v];~i;i=g[i].next){ if(g[i].to!=pre){ dfs(g[i].to,v); son[v]++; } } } bool cmp(int a,int b){ return dep[a]>dep[b]; } void init(){ memset(head,-1,sizeof head); tot=0; dep[0]=0; } int main(){ int T; scanf("%d",&T); for(int cs=1;cs<=T;cs++){ init(); int n,q; scanf("%d%d",&n,&q); for(int i=0;i<n-1;i++){ int u,v; scanf("%d%d",&u,&v); addedge(u,v); addedge(v,u); } dfs(1,0); printf("Case #%d:\n",cs); while(q--){ int m; scanf("%d",&m); int ans=n-m; for(int i=0;i<m;i++){ scanf("%d",&d[i]); } sort(d,d+m,cmp); for(int i=0;i<m;i++) son_[d[i]]=son[d[i]]; for(int i=0;i<m;i++){ if(son_[d[i]]>=2) ans++; else if(son_[d[i]]==0) son_[fa[d[i]]]--; } printf("%d\n",ans); } } return 0; }