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\n",mar[i]);
	return 0;
}

  

posted @ 2018-03-13 20:01  ws_zzy  阅读(186)  评论(0编辑  收藏  举报