zoukankan      html  css  js  c++  java
  • bzoj5329:[Sdoi2018]战略游戏

    传送门

    好题啊,就是有点难写
    对于给出的图建广义圆方树,建出广义圆方树圆方树后建虚树,然后统计虚树上的点数(包括虚边上的原树的点)
    注意特判(1)不为关键点时将(1)以及(1)连出去的边产生的贡献去掉
    还有方点不产生贡献这个有点细节
    代码(真的精神污染,没什么好看的):

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    void read(int &x) {
    	char ch; bool ok;
    	for(ok=0,ch=getchar(); !isdigit(ch); ch=getchar()) if(ch=='-') ok=1;
    	for(x=0; isdigit(ch); x=x*10+ch-'0',ch=getchar()); if(ok) x=-x;
    }
    #define rg register
    const int maxn=3e5+10;bool vis[maxn];
    int color,T,n,m,id[maxn],tot,num,dfn[maxn],f[maxn][20],dep[maxn],dis[maxn];
    int st[maxn],top,tmp,col[maxn],low[maxn],w[maxn],ans;
    struct oo
    {
    	int cnt,h[maxn],pre[maxn*2],nxt[maxn*2],v[maxn*2];
    	void add(int x,int y,int z)
    	{
    		pre[++cnt]=y,nxt[cnt]=h[x],h[x]=cnt,v[cnt]=z;
    		pre[++cnt]=x,nxt[cnt]=h[y],h[y]=cnt,v[cnt]=z;
    	}
    	void ins(int x,int y,int z){pre[++cnt]=y,nxt[cnt]=h[x],h[x]=cnt,v[cnt]=z;}
    }a,b,c;
    void tarjan(int x,int fa)
    {
    	low[x]=dfn[x]=++num,st[++top]=x;
    	for(rg int i=a.h[x];i;i=a.nxt[i])
    		if(a.pre[i]!=fa)
    		{
    			if(dfn[a.pre[i]]){low[x]=min(low[x],dfn[a.pre[i]]);continue;}
    			tarjan(a.pre[i],x);low[x]=min(low[x],low[a.pre[i]]);
    			if(low[a.pre[i]]>=dfn[x])
    			{
    				tot++;int z;
    				do
    				{
    					z=st[top--];
    					b.add(z,tot,0)/*,printf("----%d %d
    ",z,tot)*/;
    					if(a.pre[i]==z)break;
    				}while(top);
    				b.add(x,tot,0)/*,printf("----%d %d
    ",x,tot)*/;
    			}
    		}
    }
    void prepare(int x,int fa)
    {
    	id[x]=++tmp;
    	for(rg int i=1;i<20;i++)f[x][i]=f[f[x][i-1]][i-1];
    	for(rg int i=b.h[x];i;i=b.nxt[i])
    		if(b.pre[i]!=fa)
    		{
    			f[b.pre[i]][0]=x,dep[b.pre[i]]=dep[x]+1;
    			dis[b.pre[i]]=dis[x]+(b.pre[i]<=n);
    			prepare(b.pre[i],x);
    		}
    }
    int lca(int x,int y)
    {
    	if(dep[x]>dep[y])swap(x,y);int poor=dep[y]-dep[x];
    	for(rg int i=19;i>=0;i--)if(poor&(1<<i))y=f[y][i];
    	if(x==y)return x;
    	for(rg int i=19;i>=0;i--)if(f[x][i]!=f[y][i])x=f[x][i],y=f[y][i];
    	return f[x][0];
    }
    bool cmp(int x,int y){return id[x]<id[y];}
    void dfs(int x,int fa)
    {
    	for(rg int i=c.h[x];i;i=c.nxt[i])
    		if(c.pre[i]!=fa)
    		{
    			ans+=c.v[i];
    			//printf("---%d %d %d
    ",x,c.pre[i],c.v[i]);
    			dfs(c.pre[i],x);
    		}
    }
    void clear(int x,int fa)
    {
    	for(rg int i=c.h[x];i;i=c.nxt[i])
    		if(c.pre[i]!=fa)clear(c.pre[i],x);
    	c.h[x]=0;
    }
    int main()
    {
    	read(T);
    	while(T--)
    	{
    		read(n),read(m),tot=n,num=color=tmp=0,a.cnt=b.cnt=0;
    		memset(col,0,sizeof col),memset(a.h,0,sizeof a.h),memset(b.h,0,sizeof b.h);
    		memset(dfn,0,sizeof dfn),memset(low,0,sizeof low);
    		for(rg int i=1,x,y;i<=m;i++)read(x),read(y),a.add(x,y,0);
    		top=0;tarjan(1,0);prepare(1,0),read(m);
    		for(rg int i=1,t;i<=m;i++)
    		{
    			read(t);st[top=1]=1;ans=1;
    			for(rg int j=1;j<=t;j++)read(w[j]);sort(w+1,w+t+1,cmp);
    			for(rg int j=1;j<=t;j++)
    			{
    				int e=0,o=0;if(w[j]==1)continue;
    				while(top&&lca(st[top],w[j])!=st[top])
    				{
    					if(e)c.add(st[top],e,dis[e]-dis[st[top]]);
    					e=st[top],top--;
    				}
    				if(e)o=lca(e,w[j]),c.add(e,o,dis[e]-dis[o]);
    				if(o&&st[top]!=o)st[++top]=o;
    				st[++top]=w[j];
    			}
    			while(top>1)c.add(st[top],st[top-1],dis[st[top]]-dis[st[top-1]]),top--;
    			int now=0;
    			if(w[1]!=1)
    			{
    				int y=0;
    				for(rg int x=c.h[1];x;x=c.nxt[x]){now++;if(now>1)break;}
    				if(now==1)for(rg int x=c.h[1];x;x=c.nxt[x])ans=-c.v[x],y=c.pre[x];
    				now=0;
    				if(y)for(rg int x=c.h[y];x;x=c.nxt[x]){now++;if(now>1)break;}
    				if(now>1&&y<=n)ans++;
    			}
    			dfs(1,0),printf("%d
    ",ans-t),clear(1,0),c.cnt=0;
    		}
    	}
    }
    
  • 相关阅读:
    杭电2059
    杭电2058
    php错误大集合
    显示IP地址
    超简单好用的屏幕录像工具
    jquery“不再提醒"功能
    KindEditor编辑器中的class自动过滤了
    实用案例:切换面板同时切换内容
    仿51返利用户图解教程
    JavaScript调用dataTable并获取其值(ASP.Net,VS2005)
  • 原文地址:https://www.cnblogs.com/lcxer/p/10610821.html
Copyright © 2011-2022 走看看