圆方树 学习笔记

待填。。。现存代码

仙人掌的圆方树

模板题

#include<bits/stdc++.h>
#define rep(i,x,y) for(int i=x;i<=y;++i)
#define per(i,x,y) for(int i=x;i>=y;--i)
#define mar(o) for(int E=fst[o];E;E=e[E].nxt)
#define marz(o) for(int E=fstz[o];E;E=ez[E].nxt)
#define v e[E].to
#define vz ez[E].to
using namespace std;
const int n7=20123,m7=40123;
struct dino{int to,nxt,w;}e[m7],ez[m7];
int n,m,T,dcnt,ecnt,t,fst[n7],fstz[n7];
int dfn[n7],low[n7],fa[n7],dw[n7],cir[n7],s[n7];
int dep[n7],fc[n7][21],snp,snq;

int rd(){
	int shu=0;char ch=getchar();
	while(!isdigit(ch))ch=getchar();
	while(isdigit(ch))shu=(shu<<1)+(shu<<3)+ch-'0',ch=getchar();
	return shu;
}

void Dedge(int sta,int edn,int w,dino *eh,int *fsth){
	ecnt++;
	eh[ecnt]=(dino){edn,fsth[sta],w};
	fsth[sta]=ecnt;
}

void edge(int sta,int edn,int w,dino *eh,int *fsth){
	Dedge(sta,edn,w,eh,fsth),Dedge(edn,sta,w,eh,fsth);
}

void calc(int o1,int o2,int lasw){
	int tot=lasw;
    for(int o=o2;o!=o1;o=fa[o]){
		cir[o]=tot,tot+=dw[o];
	}
	dcnt++,cir[dcnt]=tot;
	for(int o=o2;o!=o1;o=fa[o]){
		edge(dcnt,o,min(cir[o],tot-cir[o]),ez,fstz);
	}
	edge(dcnt,o1,0,ez,fstz);
} 

void tarjan(int o){
	t++,dfn[o]=low[o]=t;
	mar(o){
		if(v==fa[o])continue;
		if(!dfn[v]){
			fa[v]=o,dw[v]=e[E].w;
			tarjan(v);
			low[o]=min(low[o],low[v]);
		}
		low[o]=min(low[o],dfn[v]);
		if(low[v]>dfn[o]){
			edge(o,v,e[E].w,ez,fstz);  
		}
	}
	mar(o){
		if(fa[v]!=o&&dfn[v]>dfn[o])calc(o,v,e[E].w);
	}
}

void dfs(int o){
	rep(i,1,16)fc[o][i]=fc[ fc[o][i-1] ][i-1];
	marz(o){
		if(dep[vz])continue;
		dep[vz]=dep[o]+1;
		fc[vz][0]=o,s[vz]=s[o]+ez[E].w;
		dfs(vz);
	}
}

int Dlca(int p,int q){
	if(dep[p]<dep[q])p^=q^=p^=q;
	per(i,16,0){
		if(dep[ fc[p][i] ]>=dep[q])p=fc[p][i];
	}
	if(p==q)return p;
	per(i,16,0){
		if(fc[p][i]!=fc[q][i])p=fc[p][i],q=fc[q][i];
	}
	snp=p,snq=q;
	return fc[p][0];
}

int main(){
	n=dcnt=rd(),m=rd(),T=rd();
	rep(i,1,m){
		int sta=rd(),edn=rd(),w=rd();
		edge(sta,edn,w,e,fst);
	}
	ecnt=0;
	tarjan(1);
	dep[1]=1,dfs(1);
	while(T--){
		int p=rd(),q=rd();
		int lca=Dlca(p,q),ans;
		if(lca<=n)ans=s[p]+s[q]-2*s[lca];
		else{
			ans=s[p]-s[snp]+s[q]-s[snq];
			if(cir[snp]<cir[snq])snp^=snq^=snp^=snq;
			ans=ans+min(cir[snp]-cir[snq],cir[lca]-cir[snp]+cir[snq]);
		}
		printf("%d\n",ans);
	}
	return 0;
}

一般图的圆方树

铁人两项

#include<bits/stdc++.h>
#define rep(i,x,y) for(int i=x;i<=y;++i)
#define mar(o) for(int E=fst[o];E;E=e[E].nxt)
#define marz(o) for(int E=fstz[o];E;E=ez[E].nxt)
#define v e[E].to
#define vz ez[E].to
#define lon long long
using namespace std;
const int n7=101234,z7=201234,m7=401234;
struct dino{int to,nxt;}e[m7],ez[m7];
int n,m,dcnt,ecnt,fst[n7],fstz[z7],t,dfn[n7],low[n7],top,sak[n7];
int val[z7],wei[z7],num,siz[z7];
lon ans;bool in[n7];

int rd(){
	int shu=0;char ch=getchar();
	while(!isdigit(ch))ch=getchar();
	while(isdigit(ch))shu=(shu<<1)+(shu<<3)+ch-'0',ch=getchar();
	return shu;
}

void edge(int sta,int edn,int *fsth,dino *eh){
	ecnt++;
	eh[ecnt]=(dino){edn,fsth[sta]};
	fsth[sta]=ecnt;
}

void tarjan(int o){
	num++;
	t++,dfn[o]=low[o]=t;
	top++,sak[top]=o,in[o]=1;
	mar(o){
		if(!dfn[v]){
			tarjan(v);
			low[o]=min(low[o],low[v]);
			if(low[v]!=dfn[o])continue;
			dcnt++;
			while(sak[top+1]!=v){
				edge(sak[top],dcnt,fstz,ez);
				edge(dcnt,sak[top],fstz,ez);
				val[ sak[top] ]=-1;
				in[ sak[top] ]=0;
				val[dcnt]++,top--;
			}
			val[dcnt]++,val[o]=-1;
			edge(o,dcnt,fstz,ez);
			edge(dcnt,o,fstz,ez);
		}
		else if(in[v])low[o]=min(low[o],dfn[v]);
	}
}

void dfs(int o,int fa){
	if(o<=n)siz[o]=1;
	marz(o){
		if(vz==fa)continue;
		dfs(vz,o);
		ans=ans+2ll*siz[o]*siz[vz]*val[o];
		siz[o]+=siz[vz];
	}
	ans=ans+2ll*siz[o]*(num-siz[o])*val[o];
}

int main(){
	n=dcnt=rd(),m=rd();
	rep(i,1,m){
		int sta=rd(),edn=rd();
		edge(sta,edn,fst,e);
		edge(edn,sta,fst,e);
	}
	ecnt=0;
	rep(i,1,n){
		if(dfn[i])continue;
		num=0,tarjan(i),dfs(i,0);
	}
	printf("%lld",ans);
	return 0;
}
posted @ 2021-01-04 21:39  BlankAo  阅读(214)  评论(0编辑  收藏  举报