【BZOJ3331】[BeiJing2013]压力 v-DCC缩点的板子

分析:

  不多解释,

   v-DCC缩点的板子+树上差分+LCA

   v-DCC的板子得好好学啊! 

  

受益匪浅的图(来自zkt)

有虚点,注意范围

#include<cstdio>
#include<queue>
#include<iostream>
#include<cmath>
#include<cstring>
#include<vector>
#define MAXN 200010
using namespace std;
inline int minn(int a,int b){return a<b?a:b;}
struct rr{
	int inext,to;
}bl[MAXN*10],tbl[MAXN*10];
int thead[MAXN],ttot,head[MAXN],itot;
void add(int x,int y){
	bl[++itot].to=y;
	bl[itot].inext=head[x];
	head[x]=itot;
}
void tadd(int x,int y){
	tbl[++ttot].to=y;
	tbl[ttot].inext=thead[x];
	thead[x]=ttot;
}
int root,N,M,Q;
int dfn[MAXN],low[MAXN],num;
bool cut[MAXN];
int belong[MAXN],tot;
int stack[MAXN],top;
vector<int >dcc[MAXN];
void tarjan(int u,int fa){
	dfn[u]=low[u]=++num;
	stack[++top]=u;
	if(u==root&&!head[u]){
		--top;
		dcc[++tot].push_back(u);
		return ;
	}
	int tto,flag=0;
	for(int i=head[u];i;i=bl[i].inext){
		if(bl[i].to==fa)continue;
		if(!dfn[tto=bl[i].to]){
			tarjan(tto,u);
			low[u]=minn(low[u],low[tto]);
			if(low[tto]>=dfn[u]){
				++flag;
				if(u!=root||flag>=2)
					cut[u]=true;
				++tot;
				int tan=stack[top];
				while(tan!=tto){
					dcc[tot].push_back(tan);
					tan=stack[--top];
				}
				--top;
				dcc[tot].push_back(tto);
				dcc[tot].push_back(u);
			}
		}
		else low[u]=minn(low[u],dfn[tto]);
	}
	return ;
}
int ys[MAXN];
void init(){
	int x,y;
	for(int i=1;i<=N;++i)
		if(cut[i]){
			belong[i]=++tot;
			ys[tot]=i;
		}
	for(int i=1;i<=tot;++i)
		for(int k=0;k<dcc[i].size();++k)
			if(!cut[y=dcc[i][k]])belong[y]=i;
			else tadd(i,belong[y]),tadd(belong[y],i);
}
int bin[20];
bool fw[MAXN];
int f[MAXN][20],sd[MAXN];
queue<int >dd;
void bfs(){
	int tto;
	dd.push(belong[root]);fw[belong[root]]=true;
	sd[belong[root]]=1;
	while(!dd.empty()){
		int ltop=dd.front();dd.pop();
		for(int i=thead[ltop];i;i=tbl[i].inext){
			if(fw[tto=tbl[i].to])continue;
			fw[tto]=true;
			dd.push(tto);
			sd[tto]=sd[ltop]+1;
			f[tto][0]=ltop;
			for(int j=1;bin[j]<=sd[tto];++j)
				f[tto][j]=f[f[tto][j-1]][j-1];
		}
	}
	memset(fw,0,sizeof(fw));
}
int LCA(int x,int y){
	if(sd[x]<sd[y])swap(x,y);
	for(int j=19;j>=0;--j)
		if(f[x][j]&&sd[f[x][j]]>=sd[y])
			x=f[x][j];
	if(x==y)return x;
	for(int j=19;j>=0;--j)
		if(f[x][j]&&f[y][j]&&f[x][j]!=f[y][j])
			x=f[x][j],y=f[y][j];
	return f[x][0];
}
int zui[MAXN],cha[MAXN];
void dfs(int u){
	fw[u]=true;
	int tto;
	for(int i=thead[u];i;i=tbl[i].inext){
		if(fw[tto=tbl[i].to])continue;
		dfs(tto);
		cha[u]+=cha[tto];
	}
	if(ys[u])zui[ys[u]]+=cha[u];
	return ;
}
int main(){
	root=bin[0]=1;
	for(int i=1;i<=19;++i)bin[i]=bin[i-1]<<1;
	scanf("%d%d%d",&N,&M,&Q);
	int ai,bi;
	for(int i=1;i<=M;++i){
		scanf("%d%d",&ai,&bi);
		if(ai==bi)continue;
		add(ai,bi);add(bi,ai);
	}
	tarjan(root,0);
	init();
	bfs();
	int lca;
	while(Q){
		--Q;
		scanf("%d%d",&ai,&bi);
		if(!cut[ai])++zui[ai];
		if(!cut[bi])++zui[bi];
		ai=belong[ai];bi=belong[bi];
		lca=LCA(ai,bi);
		++cha[ai];++cha[bi];
		--cha[lca];--cha[f[lca][0]];
	}
	dfs(belong[root]);
	for(int i=1;i<=N;++i)
		printf("%d\n",zui[i]);
}

猜你喜欢

转载自www.cnblogs.com/2018hzoicyf/p/11183386.html