• 【BZOJ5329】【SDOI2018】战略游戏(圆方树,虚树)


    【BZOJ5329】【SDOI2018】战略游戏(圆方树,虚树)

    题面

    BZOJ
    洛谷

    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<= 210^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

    题解

    首先把一般图构建出圆方树,
    考虑若干个点的贡献,
    显然是把他们连成一个最小的联通块,然后计算里面的圆点个数。
    这样子答案就可以通过构建虚树计算出答案啦。

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<set>
    #include<map>
    #include<vector>
    #include<queue>
    using namespace std;
    #define ll long long
    #define RG register
    #define MAX 222222
    inline int read()
    {
        RG int x=0,t=1;RG char ch=getchar();
        while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
        if(ch=='-')t=-1,ch=getchar();
        while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
        return x*t;
    }
    int Tot,n,m;
    struct Line{int v,next;};
    struct Link
    {
    	Line e[MAX<<2];
    	int h[MAX],cnt;
    	void init(){memset(h,0,sizeof(h));cnt=0;}
    	void Add(int u,int v)
    	{
    		e[++cnt]=(Line){v,h[u]};h[u]=cnt;
    		e[++cnt]=(Line){u,h[v]};h[v]=cnt;
    	}
    }G,T;
    namespace Graph
    {
    	int dfn[MAX],low[MAX],tim,S[MAX],top;
    	void init(){memset(dfn,0,sizeof(dfn));memset(low,0,sizeof(low));tim=top=0;}
    	void Tarjan(int u)
    	{
    		dfn[u]=low[u]=++tim;S[++top]=u;
    		for(int i=G.h[u];i;i=G.e[i].next)
    		{
    			int v=G.e[i].v;
    			if(!dfn[v])
    			{
    				Tarjan(v);low[u]=min(low[u],low[v]);
    				if(low[v]>=dfn[u])
    				{
    					T.Add(++Tot,u);int x;
    					do{x=S[top--];T.Add(Tot,x);}while(v!=x);
    				}
    			}
    			else low[u]=min(low[u],dfn[v]);
    		}
    	}
    }
    namespace RST
    {
    	int dfn[MAX],low[MAX],tim,fa[MAX],dep[MAX],top[MAX],size[MAX],hson[MAX],dis[MAX];
    	void init(){memset(hson,0,sizeof(hson));tim=0;}
    	void dfs1(int u,int ff)
    	{
    		fa[u]=ff;size[u]=1;dep[u]=dep[ff]+1;dis[u]=dis[ff]+(u<=n);
    		for(int i=T.h[u];i;i=T.e[i].next)
    		{
    			int v=T.e[i].v;if(v==ff)continue;
    			dfs1(v,u);size[u]+=size[v];
    			if(size[v]>size[hson[u]])hson[u]=v;
    		}
    	}
    	void dfs2(int u,int tp)
    	{
    		top[u]=tp;dfn[u]=++tim;
    		if(hson[u])dfs2(hson[u],tp);
    		for(int i=T.h[u];i;i=T.e[i].next)
    			if(T.e[i].v!=fa[u]&&T.e[i].v!=hson[u])
    				dfs2(T.e[i].v,T.e[i].v);
    		low[u]=tim;
    	}
    	int LCA(int u,int v)
    	{
    		while(top[u]^top[v])dep[top[u]]<dep[top[v]]?v=fa[top[v]]:u=fa[top[u]];
    		return dep[u]<dep[v]?u:v;
    	}
    	bool cmp(int a,int b){return dfn[a]<dfn[b];}
    	int p[MAX],S[MAX],K;
    	void Solve()
    	{
    		K=read();int ans=0,len=K;
    		for(int i=1;i<=K;++i)p[i]=read();
    		sort(&p[1],&p[K+1],cmp);
    		for(int i=K;i>1;--i)p[++K]=LCA(p[i],p[i-1]);
    		sort(&p[1],&p[K+1],cmp);K=unique(&p[1],&p[K+1])-p-1;
    		ans=p[1]<=n;
    		for(int i=1,tp=0;i<=K;++i)
    		{
    			while(tp&&low[S[tp]]<dfn[p[i]])--tp;
    			if(tp)ans+=dis[p[i]]-dis[S[tp]];S[++tp]=p[i];
    		}
    		printf("%d
    ",ans-len);
    	}
    }
    int main()
    {
    	int TCase=read();
    	while(TCase--)
    	{
    		Tot=n=read();m=read();G.init();T.init();
    		for(int i=1;i<=m;++i)G.Add(read(),read());
    		Graph::init();Graph::Tarjan(1);
    		RST::init();RST::dfs1(1,0);RST::dfs2(1,1);
    		int Q=read();
    		while(Q--)RST::Solve();
    	}
    	return 0;
    }
    
    
  • 相关阅读:
    阿里云图片在线处理
    下载文件
    adobe acrobat dc根据模板制作PDF问题总结点
    springcloud服务进行轮询采用Ribbon
    SpringCloud-Eureka-Client 启动后自动停止
    OI模板
    化学整理
    题解 P4180 [BJWC2010]严格次小生成树
    题解 CF255D 【Mr. Bender and Square】
    题解 P1541 【乌龟棋】
  • 原文地址:https://www.cnblogs.com/cjyyb/p/9103234.html
Copyright © 2020-2023  润新知