【SDOI2018】战略游戏

题面

https://www.luogu.org/problem/P4606

题解

又一次被$aysn$吊打。

// luogu-judger-enable-o2
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<vector>
#define N 200000
#define ri register int
using namespace std;

int n,m,q,s,T,cnt,clo;
int dfn[N],low[N],stk[N],top,bel[N];
int f[N][25];
int dfin[N],dfou[N],d[N];
vector<int> to[N],syx[N];
int a[N*2],ss[N*2],yy[N],stop,siz[N];
bool vis[N];

bool cmp1(int x,int y){
  return dfin[x]<dfin[y];
}

bool cmp2(int x,int y){
  int k1,k2;
  if (x>0) k1=dfin[x]; else k1=dfou[-x];
  if (y>0) k2=dfin[y]; else k2=dfou[-y];
  return k1<k2;
}

void tarjan(int x,int ff){
  dfn[x]=low[x]=++clo;
  stk[++top]=x;
  for (ri i=to[x].size()-1;i>=0;i--) if (to[x][i]!=ff) {
    if (!dfn[to[x][i]]) {
      tarjan(to[x][i],x);
      low[x]=min(low[x],low[to[x][i]]);
      if (low[to[x][i]]>=dfn[x]) {
        cnt++;
        int cc;
        do {
          cc=stk[top];
          syx[cnt].push_back(cc);
          syx[cc].push_back(cnt); 
          top--;
        }
        while (cc!=to[x][i]);
        syx[cnt].push_back(x); syx[x].push_back(cnt); 
      }
    }
    else low[x]=min(dfn[to[x][i]],low[x]);
  }
}

void dfs(int x,int ff) {
  f[x][0]=ff; d[x]=d[ff]+1; yy[x]=yy[ff]+(x<=n);
  for (ri i=1;i<=20;i++) f[x][i]=f[f[x][i-1]][i-1];
  dfin[x]=++cnt;
  for (ri i=syx[x].size()-1;i>=0;i--) if (syx[x][i]!=ff) dfs(syx[x][i],x);
  dfou[x]=++cnt;
}

int lca(int x,int y){
  if (d[x]<d[y]) swap(x,y);
  for (ri i=20;i>=0;i--) if (d[f[x][i]]>=d[y]) x=f[x][i];
  if (x==y) return x;
  for (ri i=20;i>=0;i--) if (f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i];
  return f[x][0];
}

int main(){
  scanf("%d",&T);
  for (ri ti=1;ti<=T;ti++) {
    scanf("%d %d",&n,&m);
    int u,v;
    for (ri i=1;i<=m;i++) {
      scanf("%d %d",&u,&v);
      to[u].push_back(v); to[v].push_back(u);
    }
    clo=0; top=0; cnt=n;
    memset(dfn,0,sizeof(dfn));
    memset(low,0,sizeof(low));
    memset(bel,0,sizeof(bel));
    tarjan(1,1);
    cnt=0;
    d[1]=0; yy[1]=0;
    dfs(1,1);
    scanf("%d",&q);
    for (ri ii=1;ii<=q;ii++) {
      scanf("%d",&s);
      int t=s;
      for (ri i=1;i<=s;i++) {
        scanf("%d",&a[i]);
        vis[a[i]]=1;
      }
      sort(a+1,a+s+1,cmp1);
      int ns=s;
      for (ri i=1;i<ns;i++) {
        int t=lca(a[i],a[i+1]);
        if (!vis[t]) a[++s]=t,vis[t]=1;
      }
      ns=s;
      for (ri i=1;i<=ns;i++) a[++s]=-a[i];
      sort(a+1,a+s+1,cmp2);
      stop=0;
      for (ri i=1;i<=s;i++) if (a[i]>0) {
        ss[++stop]=a[i];
        if (a[i]<=n) siz[a[i]]++;
      }
      else {
        stop--;
        if (stop) siz[ss[stop]]+=(siz[-a[i]]+yy[-a[i]]-(-a[i]<=n)-yy[ss[stop]]);
      }
      printf("%d
",siz[a[1]]-t);
      for (ri i=1;i<=s;i++) if (a[i]>0) siz[a[i]]=0,vis[a[i]]=0;
    }
    for (ri i=1;i<=cnt;i++) to[i].clear();
    for (ri i=1;i<=cnt;i++) syx[i].clear();
  }
}
原文地址:https://www.cnblogs.com/shxnb666/p/11278543.html