• 【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();
      }
    }
  • 相关阅读:
    GNU build system / autoconf 和 automake 生成 Makefile 文件
    使用you-get下载网站内嵌的视频
    ffmpeg偷懒
    GB28181的PS流完全分析(封装 / 分包发送 / 接收组包 / 解析)
    JRE与JDK的区别
    图解SQL的inner join、left join、right join、full outer join、union、union all的区别
    linux常用查看日志命令
    Hadoop2.6.2的Eclipse插件的使用
    path与classpath区别(转)
    在Eclipse上运行Spark(Standalone,Yarn-Client)
  • 原文地址:https://www.cnblogs.com/shxnb666/p/11278543.html
Copyright © 2020-2023  润新知