zoukankan      html  css  js  c++  java
  • GMOJ 4267. 图 题解

    思路

    一看到这题我就想起了gmoj3883

    本质上这道题也可以用染色的思想做,先随便建一棵树,然后每条非树边都可以看成一次染色,然后新染色的数量就是答案减少的数量。

    当然,如果一开始不是联通的就不行了(但其它方法也不行)。

    跑一下tarjan求LCA再用并查集缩点即可。

    但我没有写(一般意义上的)并查集,而是用了一种玄学的方法来做。

    具体见gmoj3883题解

    代码

    #include<cstdio>
    #include<cstring>
    #define N 500010
    #define now st[size] 
    using namespace std;
    int n,m,ans,q,s[N],last,a[N],b[N][2],ques[N][3],lca[N],up[N],dp[N],st[N],si[N];
    int qlast,qa[N],qb[N][3],least[N][2];
    bool nbi[N];
    template<typename T>void read(T &x){
    	char c=getchar();
    	for(;c<33;c=getchar());
    	for(x=0;(47<c)&&(c<58);x=x*10+c-48,c=getchar());
    }
    void add(int x,int y){
    	b[++last][0]=a[x];
    	b[last][1]=y;
    	a[x]=last;
    }
    void qadd(int x,int y,int z){
    	qb[++qlast][0]=qa[x];
    	qb[qlast][1]=y;
    	qb[qlast][2]=z;
    	qa[x]=qlast;
    }
    int root(int m){
    	return(s[m]?s[m]=root(s[m]):m);
    }
    void tarjan(){
    	int size=1;
    	st[1]=1;
    	while(size){
    		if(si[now]){
    			s[root(b[si[now]][1])]=root(now);
    			si[now]=b[si[now]][0];
    		}else{
    			si[now]=a[now];
    		}
    		for(;b[si[now]][1]==up[now]&&si[now];si[now]=b[si[now]][0]);
    		if(si[now]){
    			dp[b[si[now]][1]]=dp[now]+1;
    			st[size+1]=b[si[now]][1];
    			up[b[si[now]][1]]=now;
    			size++;
    		}else{
    			for(int i=qa[now];i;i=qb[i][0]){
    				int get=root(qb[i][1]);
    				if((get!=qb[i][1])||(get==now)){
    					lca[qb[i][2]]=get;
    				}
    			}
    			size--;		
    		}
    	}
    }
    int sg(int x,int l){
    	int re=0;
    	for(int temp;dp[x]>dp[l];x=temp){
    		temp=up[x];
    		up[x]=l;             //这条语句很有趣,因为这不是并查集,如果放在下面的if内会被卡掉
    		if(!nbi[x]){
    			nbi[x]=1;
    			re++;
    		}
    	}
    	return(re);
    }
    int main(){
    	read(n);read(m);
    	ans=n-1;
    	for(int i=1;i<=m;i++){
    		int x,y;
    		read(x);read(y);
    		if(root(x)!=root(y)){
    			add(x,y);
    			add(y,x);
    			s[root(x)]=root(y);
    		}else{
    			least[++least[0][0]][0]=x;
    			least[least[0][0]][1]=y;
    		}
    	}
    	memset(s,0,sizeof(s));
    	for(int i=1;i<=least[0][0];i++){
    		qadd(least[i][0],least[i][1],i);
    		qadd(least[i][1],least[i][0],i);
    	}
    	read(q);
    	for(int i=least[0][0]+1;i<=q+least[0][0];i++){
    		read(ques[i][0]);read(ques[i][1]);
    		qadd(ques[i][0],ques[i][1],i);
    		qadd(ques[i][1],ques[i][0],i);
    	}
    	tarjan();
    	for(int i=1;i<=least[0][0];i++){
    		ans-=sg(least[i][0],lca[i])+sg(least[i][1],lca[i]);
    	}
    	for(int i=least[0][0]+1;i<=q+least[0][0];i++){
    		ans-=sg(ques[i][0],lca[i])+sg(ques[i][1],lca[i]);
    		printf("%d
    ",ans);
    	}
    }
    
  • 相关阅读:
    uni-app拒绝授权后再次授权
    vue触底操作
    vue滚动条滚到到底部触发的方法
    pagination插件使用例子
    修改后台返回数据的字段
    v-cloak指令的作用
    修改checkbox样式
    获取selected的值
    前端工程师必备的几个实用网站
    html发展史简介(摘抄)
  • 原文地址:https://www.cnblogs.com/groundwater/p/13372453.html
Copyright © 2011-2022 走看看