zoukankan      html  css  js  c++  java
  • CF639F Bear and Chemistry

    V.CF639F Bear and Chemistry

    大毒瘤题一道。

    先边双缩点缩成森林,再对每组询问建出虚树,再连上边跑Tarjan求边双即可。

    是不是很simple?但是相信我,码起来会让你发疯的

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    int n,m,q,id[300100],lim,tree[300100],totans;
    int read(){
    	int x=0;
    	char c=getchar();
    	while(c>'9'||c<'0')c=getchar();
    	while(c>='0'&&c<='9')x=(x<<3)+(x<<1)+(c^48),c=getchar();
    	return x;
    }
    int deco(){
    	int x=(read()+totans)%n;
    	if(!x)x=n;
    //	printf("DECO:%d\n",x);
    	return id[x];
    }
    namespace ECC{
    	int dfn[300100],low[300100],tot,stk[300100],tp,head[300100],cnt,col[300100],c;
    	struct node{
    		int to,next;
    	}edge[1200100];
    	void ae(int u,int v){
    //		printf("%d %d\n",u,v);
    		edge[cnt].next=head[u],edge[cnt].to=v,head[u]=cnt++;
    		edge[cnt].next=head[v],edge[cnt].to=u,head[v]=cnt++;
    	}
    	void Tarjan(int x,int fa){
    		low[x]=dfn[x]=++tot,stk[++tp]=x;
    		for(int i=head[x],y;i!=-1;i=edge[i].next){
    			if(!dfn[y=edge[i].to])Tarjan(y,i),low[x]=min(low[x],low[y]);
    			else if((i^fa)!=1)low[x]=min(low[x],dfn[y]); 
    		}
    		if(low[x]!=dfn[x])return;
    		c++;
    		int y;
    		do col[y=stk[tp--]]=c;while(y!=x);
    	}
    }
    namespace Tree{
    	vector<int>v[300100];
    	int dfn[300100],tot,anc[300100][20],dep[300100];
    	int LCA(int x,int y){
    		if(dep[x]>dep[y])swap(x,y);
    		for(int i=19;i>=0;i--)if(dep[x]<=dep[y]-(1<<i))y=anc[y][i];
    		if(x==y)return x;
    		for(int i=19;i>=0;i--)if(anc[x][i]!=anc[y][i])x=anc[x][i],y=anc[y][i];
    		return anc[x][0];
    	}
    	void dfs(int x,int fa,int ID){
    		tree[x]=ID,dfn[x]=++tot,dep[x]=dep[fa]+1,anc[x][0]=fa;
    		for(int i=1;anc[x][i-1];i++)anc[x][i]=anc[anc[x][i-1]][i-1];
    		for(auto y:v[x])if(y!=fa)dfs(y,x,ID);
    	}
    	namespace imag{
    		int stk[300100],tp,num[300100],len,ed,inq[300100],all,U[300100],V[300100];
    		vector<int>sp;
    		void ins(int x){
    			sp.push_back(x);
    		    if(!tp){stk[++tp]=x;return;}
    		    int lca=LCA(x,stk[tp]);
    		    while(tp>=2&&dep[lca]<dep[stk[tp-1]])ECC::ae(stk[tp-1],stk[tp]),tp--;
    		    if(tp&&dep[lca]<dep[stk[tp]])ECC::ae(lca,stk[tp--]);
    		    if(!tp||stk[tp]!=lca)stk[++tp]=lca,sp.push_back(lca);
    		    stk[++tp]=x;
    		}
    		void fin(){
    			while(tp>=2)ECC::ae(stk[tp-1],stk[tp]),tp--;
            	tp=0;
    		}
    		bool solve(int ip){
    			all=len=read(),ed=read();
    			for(int i=1;i<=len;i++)inq[i]=num[i]=deco();
    			for(int i=1;i<=ed;i++)U[i]=deco(),V[i]=deco(),num[++all]=U[i],num[++all]=V[i];
    			sort(num+1,num+all+1,[](int x,int y){return tree[x]==tree[y]?dfn[x]<dfn[y]:tree[x]<tree[y];});
    			all=unique(num+1,num+all+1)-num-1;
    //			printf("QWQ:");for(int i=1;i<=len;i++)printf("%d ",inq[i]);puts("");
    //			for(int i=1;i<=ed;i++)printf("(%d,%d)",U[i],V[i]);puts("");
    //			printf("%d::",all);for(int i=1;i<=all;i++)printf("%d ",num[i]);puts("");
    			ECC::tot=ECC::cnt=ECC::c=0;
    			for(int i=1;i<=ed;i++)ECC::ae(U[i],V[i]);
    			for(int i=1;i<=all;i++){
    				if(tree[num[i]]!=tree[num[i-1]]){
    					fin();
    					if(num[i]!=tree[num[i]])sp.push_back(tree[num[i]]),stk[++tp]=tree[num[i]];
    				}
    				ins(num[i]);
    			}
    			fin();
    			for(int i=1;i<=all;i++)if(!ECC::dfn[num[i]])ECC::Tarjan(num[i],-1);
    			bool ok=true;
    			for(int i=2;i<=len;i++)if(ECC::col[inq[i]]!=ECC::col[inq[i-1]])ok=false;
    			for(auto i:sp)ECC::head[i]=-1,ECC::col[i]=ECC::dfn[i]=ECC::low[i]=0;
    			sp.clear();
    			if(!ok)return false;
    			(totans+=ip)%=n;
    			return true;
    		}
    	}
    }
    int main(){
    	n=read(),m=read(),q=read(),memset(ECC::head,-1,sizeof(ECC::head));
    	for(int i=1,x,y;i<=m;i++)x=read(),y=read(),ECC::ae(x,y);
    	for(int i=1;i<=n;i++)if(!ECC::dfn[i])ECC::Tarjan(i,-1);
    	lim=ECC::c;for(int i=1;i<=n;i++)id[i]=ECC::col[i];
    	for(int i=1;i<=n;i++)for(int j=ECC::head[i];j!=-1;j=ECC::edge[j].next)if(id[i]!=id[ECC::edge[j].to])Tree::v[id[i]].push_back(id[ECC::edge[j].to]);
    	for(int i=1;i<=lim;i++)ECC::head[i]=-1,ECC::col[i]=ECC::dfn[i]=ECC::low[i]=0;
    	for(int i=1;i<=lim;i++)if(!tree[i])Tree::dfs(i,0,i);
    //	for(int i=1;i<=n;i++)printf("%d ",id[i]);puts("");
    //	for(int i=1;i<=lim;i++)printf("%d ",tree[i]);puts("");
    	for(int i=1;i<=q;i++)puts(Tree::imag::solve(i)?"YES":"NO");
    	return 0;
    }
    

  • 相关阅读:
    Chapter 12 homework
    copy construction note
    Chapter 11 homework
    数组排序最大元素
    temporary Object and destructor
    strcpy() 函数注意的地方
    结对项目第二次作业
    结队项目——第一次作业
    软件工程实践2017第二次作业
    软件工程实践2017第一次作业
  • 原文地址:https://www.cnblogs.com/Troverld/p/14621469.html
Copyright © 2011-2022 走看看