被卡常了,复杂度正确但是TLE,求调
查看原帖
被卡常了,复杂度正确但是TLE,求调
593613
olegekei楼主2022/9/16 18:01

缩点+树上差分的板子,提交记录和代码:

#include<bits/stdc++.h>
using namespace std;
int n,m,iindex;
int p[500015];//点权 
int a[500015];//缩点后的点权 
int scc[500015];//缩点后存点的数组 
int dfn[500015],low[500015];//dfn时间戳(访问到当前节点的时间),low为当前环(如果有的话)的起点节点 
int stac[500015],top;//栈 
vector<int>e[500015];//vector建边 
int cnt=0;//统计缩点数量 
void tarjan(int x,int fa){
	if(dfn[x])return;//已被访问过 
	low[x]=dfn[x]=++iindex;//时间戳和low数组处理 
	stac[++top]=x;//入栈 
	for(int i=0;i<e[x].size();i++){
		int v=e[x][i];
		if(v==fa)continue;
		if(!dfn[v]){//当前点未被访问过 
			tarjan(v,x);//tarjan下一层(可能有环,也可能在链上) 
			low[x]=min(low[x],low[v]);//如果此处有环,low[x]将被修改 
		}
		else if(!scc[v])low[x]=min(low[x],dfn[v]);//注意此处v不在环内才能修改low[x],保证算法正确性 
	}
	if(dfn[x]==low[x]){//回到原点(将从x开始缩点) 
		int y;cnt++; 
		while(y=stac[top--]){
			scc[y]=cnt;//缩点 
			a[cnt]+=p[y];//点权也缩 
			if(x==y)break;//缩完了跑路 
		}
	}
}
vector<int>g[500015];//缩点后的图 
int dep[500015];//树的深度 
int jump[500015][19]; 
int b[500015];//差分数组 
inline void swap(int &x,int &y){x^=y^=x^=y;return;}//据说是顶级优化swap 
void dfs(int u,int f){
	dep[u]=dep[f]+1;
	jump[u][0]=f;
for(int j=1;j<=18;j++){ 
	if(dep[u]<(j<<1))break;
	jump[u][j]=jump[jump[u][j-1]][j-1];
}
	for(int i=0;i<g[u].size();i++){
		int v=g[u][i];
		if(v==f)continue;
		dfs(v,u);
	}
}
inline int lca(int x,int y){
	if(dep[x]<dep[y])swap(x,y);
	for(int j=18;j>=0;j--){
		if((dep[x]-dep[y]&(1<<j)))x=jump[x][j];
	}
	if(x==y)return x;
	for(int j=18;j>=0;j--){
		if(jump[x][j]!=jump[y][j]){
			x=jump[x][j];
			y=jump[y][j];
		}
	}
	return jump[x][0];
}
void ask(int u,int f){
	for(int i=0;i<g[u].size();i++){
        int v=g[u][i];
        if (v==f) continue;
        ask(v,u);
        b[u]+=b[v];
    }
}
void debug(){//debug更方便理解缩点过程 
	cout<<"scc:";
	for(int i=1;i<=n;i++)cout<<scc[i]<<' ';
	cout<<"\ndfn:";
	for(int i=1;i<=n;i++)cout<<dfn[i]<<' ';
	cout<<"\nlow:";
	for(int i=1;i<=n;i++)cout<<low[i]<<' ';
	cout<<'\n';
	return ;
}
void debug2(){
	cout<<"Scc:";
	for(int i=1;i<=n;i++){
		cout<<scc[i]<<' ';
	}cout<<'\n';
	cout<<"b:";
	for(int i=1;i<=n;i++){
		cout<<b[scc[i]]<<' ';
	}cout<<'\n';
}
int main(){
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
cin>>n>>m;
for(int i=1;i<=n;i++)cin>>p[i];
for(int i=1;i<=m;i++){
	int u,v;
	cin>>u>>v;
	e[u].push_back(v);
	e[v].push_back(u);
}
tarjan(1,0);//tarjan 
//for(int i=1;i<=cnt;i++)cout<<a[i]<<' ';cout<<'\n';
//debug(); 
for(int i=1;i<=n;i++){
	for(int j=0;j<e[i].size();j++){//建缩点后的图 
		int v=e[i][j];
		if(scc[i]!=scc[v]){
			g[scc[i]].push_back(scc[v]);
			g[scc[v]].push_back(scc[i]);
		}
	}
}
dfs(scc[1],0);
int Q;
cin>>Q;
while(Q--){
	int x,y;
	cin>>x>>y;
	x=scc[x];y=scc[y];
	int u=lca(x,y);
	b[x]++;b[y]++;b[u]--;b[jump[u][0]]--;
}
ask(scc[1],0);
int ans=0;
for(int i=1;i<=cnt;i++){
	if(b[i])ans+=a[i];
}
//debug2();
cout<<ans;
}
2022/9/16 18:01
加载中...