zoukankan      html  css  js  c++  java
  • BZOJ5329 SDOI2018 战略游戏

    传送门

    补的第一道SDOI2018?

    圆方树上建虚树 欢乐多又多【大雾

    大概就是求对于S个点 问删掉一个点使它们不完全连通的方案数

    那么我们可以看出 这个其实就是求两两路径并上的割点数量

    那么 圆方树来解决是最好的办法【好像也没有别的办法

    然后我们发现如果两两统计LCA的话,复杂度是S^2无法接受

    可以看出 这个过程和虚树的构建过程十分相似

    所以 我们就可以建出虚树 统计答案即可

    附代码。

     #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<stack>
    #define inf 20021225
    #define ll long long
    #define mxm 200100
    #define mxn 100100
    using namespace std;
    
    struct edge{int to,lt;}p[mxm<<1],t[mxm<<1],e[mxm<<1];
    // p 原图 t 虚树 e 圆方树 
    int ip[mxn],it[mxn<<1],in[mxn<<1];
    int cnp,cntt,cnt,pt,poi[mxm],n,m;
    int dfn[mxn<<1],low[mxn],dep[mxn<<1],tot;
    int f[mxn<<1][20],g[mxn<<1];
    int stk[mxn<<1],num;bool spc[mxn<<1];
    // 注意不要用混!!! 
    void add(int x,int y)
    {
    	e[++cnt].to=y;e[cnt].lt=in[x];in[x]=cnt;
    	e[++cnt].to=x;e[cnt].lt=in[y];in[y]=cnt;
    }
    void app(int x,int y)
    {
    	p[++cnp].to=y;p[cnp].lt=ip[x];ip[x]=cnp;
    	p[++cnp].to=x;p[cnp].lt=ip[y];ip[y]=cnp;
    }
    void att(int x,int y)//只建儿子边 
    {
    	t[++cntt].to=y;t[cntt].lt=it[x];it[x]=cntt;
    }
    stack<int> tt; 
    void tarjan(int x,int ff)
    {
    	dfn[x]=low[x]=++tot;tt.push(x);
    	for(int i=ip[x];i;i=p[i].lt)
    	{
    		int y=p[i].to;if(y==ff)	continue;
    		if(!dfn[y])
    		{
    			tarjan(y,x);
    			low[x]=min(low[y],low[x]);
    			if(low[y]>=dfn[x])
    			{
    				++num;add(num,x);int tmp;
    				do
    				{
    					tmp=tt.top();tt.pop();
    					add(num,tmp);
    				}while(tmp!=y);
    			}
    		}
    		else
    			low[x]=min(low[x],dfn[y]);
    	}
    }
    void dfs(int x)
    {
    	dfn[x]=++tot;//记得清零!! 
    	for(int i=1;i<20;i++)
    		f[x][i]=f[f[x][i-1]][i-1];
    	for(int i=in[x];i;i=e[i].lt)
    	{
    		int y=e[i].to;if(dep[y])	continue;
    		f[y][0]=x;g[y]=g[x]+(y<=n);
    		dep[y]=dep[x]+1;dfs(y);
    	}
    }
    void maketree()//建圆方树
    {
    	for(int i=1;i<=n;i++)
    		if(!dfn[i])	tarjan(i,i);
    	g[1]=dep[1]=1;tot=0;dfs(1);
    }
    int LCA(int x,int y)
    {
    	if(dep[x]<dep[y])	swap(x,y);
    	int len=dep[x]-dep[y];
    	for(int i=19;~i;i--)	if(len&(1<<i))	x=f[x][i];
    	if(x==y)	return x;
    	for(int i=19;~i;i--)	if(f[x][i]!=f[y][i])
    		x=f[x][i],y=f[y][i];
    	return f[x][0];
    }
    void insert(int x)
    {
    	if(!stk[0]){stk[++stk[0]]=x;return;}
    	int lca=LCA(stk[stk[0]],x);
    	if(lca!=stk[stk[0]])
    	while(stk[0]>1)
    	{
    		int z=stk[stk[0]-1];
    		if(dfn[z]>dfn[lca])	att(z,stk[stk[0]]),stk[0]--;
    		else if(z==lca){att(z,stk[stk[0]]);stk[0]--;break;}
    		else if(dfn[z]<dfn[lca]){att(lca,stk[stk[0]]),stk[stk[0]]=lca;break;}
    	}
    	if(stk[stk[0]]!=x)	stk[++stk[0]]=x;
    }
    bool cmp(int x,int y){return dfn[x]<dfn[y];}
    int ans,rt;//清零!! 
    void build()
    {
    	sort(poi+1,poi+pt+1,cmp);
    	rt=poi[1];cntt=0;
    	for(int i=2;i<=pt;i++)	rt=LCA(rt,poi[i]);
    	stk[0]=0;insert(rt);
    	for(int i=1;i<=pt;i++)	insert(poi[i]);
    	while(stk[0]>1)	att(stk[stk[0]-1],stk[stk[0]]),stk[0]--;
    }
    void query(int x)
    {
    	for(int &i=it[x];i;i=t[i].lt)
    	{
    		int y=t[i].to;
    		ans+=g[y]-g[x];
    		query(y);
    	}
    	spc[x]=0;
    }
    void init()
    {
    	memset(in,0,sizeof(in));
    	memset(ip,0,sizeof(ip));
    	memset(f,0,sizeof(f));
    	memset(g,0,sizeof(g));
    	memset(dep,0,sizeof(dep));
    	memset(dfn,0,sizeof(dfn));
    	memset(low,0,sizeof(low));
    	cnt=cnp=tot=0;
    	while(!tt.empty())	tt.pop();
    }
    int main()
    {
    	int T,x,y,q;
    	scanf("%d",&T);
    	while(T--)
    	{
    		init();
    		scanf("%d%d",&n,&m);num=n;
    		for(int i=1;i<=m;i++)
    			scanf("%d%d",&x,&y),app(x,y);
    		maketree();
    		scanf("%d",&q);
    		for(int i=1;i<=q;i++)
    		{
    			scanf("%d",&pt);
    			for(int j=1;j<=pt;j++)	scanf("%d",&poi[j]),spc[poi[j]]=1;
    			build();ans=(rt<=n)?1:0;query(rt);ans-=pt;
    			printf("%d
    ",ans);
    		}
    	}
    	return 0;
    }
  • 相关阅读:
    添加语句<tx:annotation-driven transaction-manager="txManager"/>报错
    ssh学习(1)
    C.Sum 2017 ACM-ICPC 亚洲区(西安赛区)网络赛
    Problem 1004-2017 ACM/ICPC Asia Regional Shenyang Online
    Problem 1002-2017 ACM/ICPC Asia Regional Shenyang Online
    2017 ACM-ICPC 亚洲区(乌鲁木齐赛区)网络赛- A. Banana
    HDU 1052 Tian Ji -- The Horse Racing(贪心)
    HDU 1236 排名
    HDU 2550 百步穿杨
    HDU 1084 What Is Your Grade?(排序)
  • 原文地址:https://www.cnblogs.com/hanyuweining/p/10321923.html
Copyright © 2011-2022 走看看