• BZOJ 3331 [BeiJing2013]压力


    题解:

    建出圆方树

    先求点双,然后每个点向点双代表的方点连边

    然后树上差分一下

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<vector>
    #include<queue>
    #include<stack>
    using namespace std;
    const int maxn=400009;
    typedef pair<int,int> fuck;
    
    int n,m,t;
    int rx[maxn],ry[maxn];
    
    int cntedge=0;
    int head[maxn]={0};
    int to[maxn<<1],nex[maxn<<1];
    void Addedge(int x,int y){
    	nex[++cntedge]=head[x];
    	to[cntedge]=y;
    	head[x]=cntedge;
    }
    
    
    int bcccnt=0,dfsclock=0;
    int pre[maxn],lowlink[maxn],bccnum[maxn];
    stack<fuck>S;
    vector<int>B[maxn];
    
    void Dfs(int u,int fa){
    	pre[u]=lowlink[u]=++dfsclock;
    	
    	for(int i=head[u];i;i=nex[i]){
    		int v=to[i];
    		if(v==fa)continue;
    		if(!pre[v]){
    			S.push(make_pair(u,to[i]));
    			Dfs(v,u);
    			lowlink[u]=min(lowlink[u],lowlink[v]);
    			if(lowlink[v]>=pre[u]){
    				++bcccnt;
    				for(;;){
    					pair<int,int>P=S.top();S.pop();
    					if(bccnum[P.first]!=bcccnt){
    						bccnum[P.first]=bcccnt;
    						B[bcccnt].push_back(P.first);
    					}
    					if(bccnum[P.second]!=bcccnt){
    						bccnum[P.second]=bcccnt;
    						B[bcccnt].push_back(P.second);
    					}
    					if(P==make_pair(u,v))break;
    				}
    			}
    		}else{
    			lowlink[u]=min(lowlink[u],pre[v]);
    		}
    	}
    }
    
    int totn;
    int f[maxn][20],dep[maxn];
    void Dfs2(int x,int fa){
    	f[x][0]=fa;
    	dep[x]=dep[fa]+1;
    	for(int i=head[x];i;i=nex[i]){
    		if(to[i]==fa)continue;
    		Dfs2(to[i],x);
    	}
    }
    
    void LCAinit(){
    	for(int j=1;j<=19;++j){
    		for(int i=1;i<=totn;++i){
    			f[i][j]=f[f[i][j-1]][j-1];
    		}
    	}
    }
    int Getlca(int u,int v){
    	if(dep[u]<dep[v])swap(u,v);
    	for(int j=19;j>=0;--j){
    		if(dep[f[u][j]]>=dep[v]){
    			u=f[u][j];
    		}
    	}
    	if(u==v)return u;
    	for(int j=19;j>=0;--j){
    		if(f[u][j]!=f[v][j]){
    			u=f[u][j];v=f[v][j];
    		}
    	}
    	return f[u][0];
    }
    
    int mar[maxn];
    void Dp(int x,int fa){
    	for(int i=head[x];i;i=nex[i]){
    		if(to[i]==fa)continue;
    		Dp(to[i],x);
    		mar[x]+=mar[to[i]];
    	}
    }
    
    int father[maxn];
    int Getf(int x){
    	if(father[x]==x)return x;
    	return father[x]=Getf(father[x]);
    }
    void Unionn(int x,int y){
    	int fx=Getf(x);
    	int fy=Getf(y);
    	if(fx!=fy)father[fx]=fy;
    }
    
    int main(){
    	scanf("%d%d%d",&n,&m,&t);
    	for(int i=1;i<=m;++i){
    		scanf("%d%d",&rx[i],&ry[i]);
    		Addedge(rx[i],ry[i]);
    		Addedge(ry[i],rx[i]);
    	}
    	Dfs(1,0);
    	
    	cntedge=0;
    	memset(head,0,sizeof(head));
    	totn=n;
    	for(int i=1;i<=n+bcccnt;++i)father[i]=i;
    	for(int u=1;u<=bcccnt;++u){
    		++totn;
    		for(int i=0;i<B[u].size();++i){
    			int v=B[u][i];
    			Addedge(v,totn);
    			Addedge(totn,v);
    			Unionn(totn,v);
    		}
    	}
    //	for(int i=1;i<=m;++i){
    //		if(Getf(rx[i])!=Getf(ry[i])){
    //			Addedge(rx[i],ry[i]);
    //			Addedge(ry[i],rx[i]);
    //			Unionn(rx[i],ry[i]);
    //		}
    //	}
    	Dfs2(1,0);
    	LCAinit();
    	 
    	while(t--){
    		int x,y;
    		scanf("%d%d",&x,&y);
    		int lca=Getlca(x,y);
    		mar[x]++;mar[y]++;mar[lca]--;mar[f[lca][0]]--;
    	}
    	
    	Dp(1,0);
    	
    	for(int i=1;i<=n;++i)printf("%d
    ",mar[i]);
    	return 0;
    }
    

      

    自己还是太辣鸡了
  • 相关阅读:
    验证码
    Linux 常用命令
    WTM_LayUI 二级联动
    文件上传漏洞及绕过
    Web For Pentester靶场(xss部分)
    文件上传漏洞fuzz字典生成脚本小工具分享
    两种搭建个人博客方法
    DVWA(xss部分源码分析)
    xss小游戏源码分析
    linux下启动tomcat报错:The BASEDIR environment...
  • 原文地址:https://www.cnblogs.com/zzyer/p/8561099.html
Copyright © 2020-2023  润新知