zoukankan      html  css  js  c++  java
  • [BZOJ5329][Sdoi2018]战略游戏 圆方树+虚树

    5329: [Sdoi2018]战略游戏

    Time Limit: 30 Sec  Memory Limit: 512 MB
    Submit: 174  Solved: 109
    [Submit][Status][Discuss]

    Description

    省选临近,放飞自我的小Q无心刷题,于是怂恿小C和他一起颓废,玩起了一款战略游戏。
    这款战略游戏的地图由n个城市以及m条连接这些城市的双向道路构成,并且从任意一个城市出发总能沿着道路走到
    任意其他城市。现在小C已经占领了其中至少两个城市,小Q可以摧毁一个小C没占领的城市,同时摧毁所有连接这
    个城市的道路。只要在摧毁这个城市之后能够找到某两个小C占领的城市u和v,使得从u出发沿着道路无论如何都不
    能走到v,那么小Q就能赢下这一局游戏。
    小Q和小C一共进行了q局游戏,每一局游戏会给出小C占领的城市集合S
    你需要帮小Q数出有多少个城市在他摧毁之后能够让他赢下这一局游戏。

    Input

    第一行包含一个正整数T,表示测试数据的组数,
    对于每组测试数据,
    第一行是两个整数n和m,表示地图的城市数和道路数,
    接下来m行,每行包含两个整数u和v~(1<=u<v<=n)
    表示第u个城市和第v个城市之间有一条道路,同一对城市之间可能有多条道路连接,
    第m+1是一个整数q,表示游戏的局数,
    接下来q行,每行先给出一个整数|S|(2<=|S|<=n)
    表示小C占领的城市数量,然后给出|S|个整数s1,s2,...s|S|,(1<=s1<s2<s|S|<=n),表示小C占领的城市。
    1<= T<= 10,
    2<= n<= 10^5 且 n-1<= m<= 2*10^5,
    1<= q<= 10^5,
    对于每组测试数据,有Sigma|S|<= 2*10^5

    Output

    对于每一局游戏,输出一行,包含一个整数,表示这一局游戏中有多少个城市在小Q摧毁之后能够让他赢下这一局游戏。

    Sample Input

    2
    7 6
    1 2
    1 3
    2 4
    2 5
    3 6
    3 7
    3
    2 1 2
    3 2 3 4
    4 4 5 6 7
    6 6
    1 2
    1 3
    2 3
    1 4
    2 5
    3 6
    4
    3 1 2 3
    3 1 2 6
    3 1 5 6
    3 4 5 6

    Sample Output

    0
    1
    3
    0
    1
    2
    3

    HINT

     

    Source

    对原图建立圆方树,显然答案为关键点间的圆点数,对圆方树建立虚树即可。

      1 #include<iostream>
      2 #include<cstring>
      3 #include<cstdlib>
      4 #include<cstdio>
      5 #include<cmath>
      6 #include<algorithm>
      7 #define maxn 400005
      8 using namespace std;
      9 inline int read() {
     10     int x=0,f=1;char ch=getchar();
     11     for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-1;
     12     for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';
     13     return x*f;
     14 }
     15 int T;
     16 int n,m;
     17 struct edge {int to,nxt;}e[maxn*2],e1[maxn*2];
     18 int head[maxn],cnt,head1[maxn],cnt1;
     19 inline void add(int u,int v) {e[++cnt].nxt=head[u];e[cnt].to=v;head[u]=cnt;}
     20 inline void add1(int u,int v) {e1[++cnt1].nxt=head1[u];e1[cnt1].to=v;head1[u]=cnt1;}
     21 int dfn[maxn],low[maxn],tim,sta[maxn],top,tot;
     22 int f[maxn][20],dep[maxn],dis[maxn];
     23 inline void init() {
     24     memset(head,0,sizeof(head));
     25     memset(head1,0,sizeof(head1));
     26     memset(dfn,0,sizeof(dfn));
     27     memset(low,0,sizeof(low));
     28     memset(dis,0,sizeof(dis));
     29     memset(dep,0,sizeof(dep));
     30     memset(f,0,sizeof(f));
     31     cnt=0;cnt1=0;tim=0;top=0;tot=0;
     32 }
     33 inline void tarjan(int x) {
     34     dfn[x]=low[x]=++tim;sta[++top]=x;
     35     for(int i=head[x];i;i=e[i].nxt) {
     36         int to=e[i].to;
     37         if(dfn[to]) low[x]=min(low[x],dfn[to]);
     38         else {
     39             tarjan(to);low[x]=min(low[x],low[to]);
     40             if(low[to]>=dfn[x]) {
     41                 ++tot;
     42                 while(sta[top]!=to){add1(tot,sta[top]);add1(sta[top],tot);top--;}
     43                 add1(sta[top],tot);add1(tot,sta[top]);top--;
     44                 add1(x,tot);add1(tot,x);
     45             }
     46         }
     47     }
     48 }
     49 inline void dfs(int x,int fa) {
     50     dfn[x]=++tim;
     51     for(int i=1;i<20&&(1<<i)<=dep[x];i++) f[x][i]=f[f[x][i-1]][i-1];
     52     for(int i=head1[x];i;i=e1[i].nxt) {
     53         int to=e1[i].to;if(to==fa) continue;
     54         f[to][0]=x;dep[to]=dep[x]+1;dis[to]=dis[x]+(to<=n);
     55         dfs(to,x);
     56     }
     57 }
     58 inline int getlca(int x,int y) {
     59     if(dep[x]<dep[y]) swap(x,y);
     60     int t=dep[x]-dep[y];
     61      
     62     for(int i=0;i<20;i++) if((1<<i)&t) x=f[x][i];
     63     for(int i=19;i>=0;i--) if(f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i];
     64     return x==y?x:f[x][0];
     65 }
     66 int a[maxn];
     67 inline bool cmp(int t1,int t2) {return dfn[t1]<dfn[t2];}
     68 int main() {
     69     //freopen("1.in","r",stdin);
     70     //freopen("1.out","w",stdout);
     71     T=read();
     72     while(T--) {
     73         init();
     74         n=read(),m=read();tot=n;
     75         for(int i=1;i<=m;i++) {
     76             int u=read(),v=read();
     77             add(u,v);add(v,u);          
     78         }
     79         tarjan(1);memset(dfn,0,sizeof(dfn));tim=0;dis[1]=1;dep[1]=1;dfs(1,0);top=0;
     80         int Q=read();
     81         while(Q--) {
     82             top=0;
     83             int q=read(),ans=0;
     84             for(int i=1;i<=q;i++) a[i]=read();
     85             sort(a+1,a+q+1,cmp);
     86             sta[++top]=a[1];
     87             for(int i=2;i<=q;i++) {
     88                 int lca=getlca(a[i],sta[top]);
     89                 while(top>1&&dep[sta[top-1]]>=dep[lca]) {
     90                     ans+=dis[sta[top]]-dis[sta[top-1]];top--;
     91                 }
     92                 if(sta[top]!=lca) {ans+=dis[sta[top]]-dis[lca],sta[top]=lca;}
     93                 sta[++top]=a[i];
     94             }
     95             while(top>1) {ans+=dis[sta[top]]-dis[sta[top-1]],top--;}
     96             ans+=(sta[top]<=n)-q;
     97             printf("%d
    ",ans);
     98         }
     99     }
    100 }
    101 
    View Code
  • 相关阅读:
    【Python web 开发】购物车功能需求分析和加入购物车功能实现
    【Python web 开发】第九章开发总结
    【Python web 开发】个人中心-用户的收货地址
    【Python web 开发】个人中心-用户留言功能
    自适应网页设计(Responsive Web Design)
    无废话MVC系列教程
    标准查询运算符
    系统泛型委托
    var隐式类型
    自动属性
  • 原文地址:https://www.cnblogs.com/wls001/p/9634193.html
Copyright © 2011-2022 走看看