求助卡常(tarjan求LCA)
查看原帖
求助卡常(tarjan求LCA)
592126
13402805827wuaiyang楼主2023/6/22 21:56

复杂度正确,但#8,#9TLE,都是一点1.0几秒。请求大佬传授卡常技巧(码风可能略微不适)

#include <bits/stdc++.h>
using namespace std;
inline unsigned int read(){
	unsigned int num=0;
	char ls=getchar();
	while(ls>'9'||ls<'0') ls=getchar();
	while(ls<='9'&&ls>='0') num=num*10+(ls-'0'),ls=getchar();
	return num;
}
bool c=0;
const unsigned int MAXN=5e5+5,MAXM=2e6+5,MAXQ=1e6+5;
unsigned int head[2][MAXN],tot[2]={1,1},head_q[MAXN],q_tot=1;
unsigned int num[2][MAXN];
struct L{
	unsigned int to,nxt;
}lin[2][MAXM*2],qes[MAXQ*2];
#define lin lin[c]
#define head head[c]
#define tot tot[c]
#define num num[c]
inline void add(const unsigned int u,const unsigned int v){
	lin[++tot]=(L){v,head[u]};
	head[u]=tot;
}
inline void add_q(const unsigned int u,const unsigned int v){
	qes[++q_tot]=(L){v,head_q[u]};
	head_q[u]=q_tot;
}
unsigned int n,m,q,u,v;
unsigned int low[MAXN],dfn[MAXN],dfn_num,fa[MAXN],fa_num,fa_lin[MAXN],bridge[MAXM*2];
void tarjan(const unsigned int x){
	low[x]=dfn[x]=++dfn_num;
	for(register unsigned int i=head[x];i;i=lin[i].nxt){
		if(i==(fa_lin[x]^1)) continue;
		register unsigned int to=lin[i].to;
		if(dfn[to]) low[x]=min(dfn[to],low[x]);
		else{
			fa_lin[to]=i,tarjan(to),low[x]=min(low[x],low[to]);
			if(low[to]>dfn[x]) bridge[i]=bridge[i^1]=1;
		}
	}
}
unsigned int bcj[MAXN],cf[MAXN],tree_fa[MAXN];
bool bjt_tree[MAXN];
unsigned int find(unsigned int x){
	if(bcj[x]!=x) bcj[x]=find(bcj[x]);
	return bcj[x];
}
void LCA_tarjan(const unsigned int x){
	bjt_tree[x]=1;
	for(register unsigned int i=head_q[x];i;i=qes[i].nxt){
		register unsigned int to=qes[i].to;
		if(!bjt_tree[to]) continue;
		find(to);
		cf[x]++;
		cf[to]++;
		cf[bcj[to]]--;
		cf[tree_fa[bcj[to]]]--;
	}
	for(register unsigned int i=head[x];i;i=lin[i].nxt){
		register  unsigned int to=lin[i].to;
		if(bjt_tree[to]) continue;
		tree_fa[to]=x;
		LCA_tarjan(to);
		bcj[to]=x;
	}
}
unsigned int ans=0;
void get_qz(const unsigned int x){
	bjt_tree[x]=0;
	for(register unsigned int i=head[x];i;i=lin[i].nxt){
		register unsigned int to=lin[i].to;
		if(bjt_tree[to]==0) continue;
		get_qz(to);
		cf[x]+=cf[to]; 
	}
	if(cf[x]>0) ans+=num[x];
}
inline void reset(){
	for(register unsigned int i=1;i<=n;i++){
		register  unsigned int z=num[i];
		c=1,num[fa[i]]+=z,c=0;
		for(unsigned int j=head[i];j;j=lin[j].nxt){
			register unsigned int to=lin[j].to;
			if(fa[to]==fa[i]) continue;
			c=1,add(fa[i],fa[to]),c=0;
		}
	}
	c=1;
}
void get_fa(const unsigned int x){
	fa[x]=fa_num;
	for(register unsigned int i=head[x];i;i=lin[i].nxt){
		if(bridge[i]) continue;
		register unsigned int to=lin[i].to;
		if(fa[to]) continue;
		get_fa(to);
	}
}
inline void input(){
	n=read(),m=read();
	for(register unsigned int i=1;i<=n;i++) num[i]=read();
	for(register unsigned int i=1;i<=m;i++) u=read(),v=read(),add(u,v),add(v,u);
}
inline void sd(){
	for(register unsigned int i=1;i<=n;i++) if(!dfn[i]) tarjan(i);
	for(register unsigned int i=1;i<=n;i++) if(!fa[i]) fa_num++,get_fa(i);
	reset();
}

inline void answer(){
	q=read();
	for(unsigned int i=1;i<=q;i++) u=read(),v=read(),add_q(fa[u],fa[v]),add_q(fa[v],fa[u]);
	for(unsigned int i=1;i<=fa_num;i++) bcj[i]=i;
	LCA_tarjan(1);
	get_qz(1);
	printf("%d",ans);
}
int main(){
	input();
	sd();
	answer();
	return 0;
}
2023/6/22 21:56
加载中...