【bzoj 5329】戰略遊戲(圓方樹+虛樹)

傳送門biu~
對於原圖建圓方樹,每次詢問在圓方樹上建虛樹,樹上的每一個圓點都符合條件,統計圓點個數即可。

#include<bits/stdc++.h>
#define N 200005
using namespace std;
int n,m,tot,top,tim,TIM,s[N];
int stac[N],dfn[N],low[N],dep[N<<1],val[N<<1],fa[N<<1][20],DFN[N<<1];
int head[N],nex[N<<1],to[N<<1],tp;
inline void add(int x,int y){
    nex[++tp]=head[x];
    head[x]=tp;
    to[tp]=y;
}
int HEAD[N<<1],NEX[N<<3],TO[N<<3],TP;
inline void ADD(int x,int y){
    NEX[++TP]=HEAD[x];
    HEAD[x]=TP;
    TO[TP]=y;
}
inline void init(){
    top=tim=TIM=0;  
    memset(fa,0,sizeof fa);
    memset(head,-1,sizeof head),tp=0;   
    memset(HEAD,-1,sizeof HEAD),TP=0;
    memset(dfn,0,sizeof dfn),memset(low,0,sizeof low);
    memset(dep,0,sizeof dep),memset(val,0,sizeof val);
}
void tarjan(int x){
    dfn[x]=low[x]=++tim;
    val[x]=1; stac[++top]=x;
    for(int v,p,i=head[x];~i;i=nex[i]){
        if(dfn[v=to[i]]) low[x]=min(low[x],dfn[v]);
        else{
            tarjan(v),low[x]=min(low[x],low[v]);
            if(low[v]>=dfn[x]){
                ++tot;
                while((p=stac[top])^v) ADD(p,tot),ADD(tot,p),--top;
                p=stac[top],ADD(p,tot),ADD(tot,p),--top;
                ADD(x,tot),ADD(tot,x);
            }
        }
    }
}
void dfs(int x){
    DFN[x]=++TIM;
    for(int i=1;(1<<i)<=dep[x];++i) fa[x][i]=fa[fa[x][i-1]][i-1];
    for(int v,i=HEAD[x];~i;i=NEX[i]){
        if((v=TO[i])==fa[x][0]) continue;
        dep[v]=dep[x]+1,val[v]+=val[x],fa[v][0]=x;
        dfs(v);
    }
}
inline int lca(int x,int y){
    if(dep[x]<dep[y])   swap(x,y);
    int len(dep[x]-dep[y]);
    for(int i=0;(1<<i)<=len;++i)
        if((1<<i)&len)  x=fa[x][i];
    if(x==y)    return x;
    for(int i=19;~i;--i)
        if(fa[x][i]^fa[y][i]) x=fa[x][i],y=fa[y][i];
    return fa[x][0];
}
inline bool cmp(int a,int b){return DFN[a]<DFN[b];}
inline int GetAns(){
    int res(0);
    sort(s+1,s+s[0]+1,cmp);
    int rt=lca(s[1],s[s[0]]);
    stac[top=1]=rt;
    for(int i=1;i<=s[0];++i){
        int LCA=lca(s[i],stac[top]);
        while(1){
            if(dep[stac[top-1]]<=dep[LCA]){
                res+=val[stac[top]]-val[LCA],--top;
                if(stac[top]^LCA)   stac[++top]=LCA;
                break;
            }
            res+=val[stac[top]]-val[stac[top-1]],--top;
        }
        if(s[i]^stac[top])  stac[++top]=s[i];
    }
    while(top>1) res+=val[stac[top]]-val[stac[top-1]],--top;
    return res+(rt<=n)-s[0];
}
inline void solve(){
    scanf("%d%d",&n,&m),tot=n;
    for(int u,v,i=0;i<m;++i)    scanf("%d%d",&u,&v),add(u,v),add(v,u);
    tarjan(1),dfs(1);
    int Q;scanf("%d",&Q);
    while(Q--){
        scanf("%d",&s[0]);
        for(int i=1;i<=s[0];++i)    scanf("%d",&s[i]);
        printf("%d\n",GetAns());
    }
}
int main(){
    int T;scanf("%d",&T);
    while(T--){
        init();
        solve(); 
    }
    return 0;
} 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章