图论-生成树-次小生成树

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/TengWan_Alunl/article/details/83048356

dfs预处理的时候光顾着处理最大值与次大值了,竟然忘记处理祖先值。。。

#include<bits/stdc++.h>
#define rep(i,l,r) for(int i=(l);i<=(r);i++)
#define per(i,r,l) for(int i=(r);i>=(l);i--)
#define random(l,r) ((l)+rand()%((r)-(l)+1))
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
const int inf=1e9+10,N=1e6+1010,M=3e6+1010;
const double eps=1e-6;
struct edge{int a,b,w;}e[M];
ll ans;
int n,m,f[N],dif=inf;
int head[N],nxt[N*2],to[N*2],w[N*2],len;//边数只需开N*2就行了,因为只存生成树上的边。 
bool used[M];
inline void addedge(int a,int b,int ww){ nxt[++len]=head[a]; head[a]=len; to[len]=b; w[len]=ww; }
bool compare(edge a,edge b){ return a.w<b.w;}
int getf(int v){ return f[v]==v?v:f[v]=getf(f[v]);}
inline void merge(int a,int b){ f[getf(b)]=getf(a);}
inline void Kruskal(){
	rep(i,1,n) f[i]=i;
	sort(e+1,e+1+m,compare);
	rep(i,1,m){
		int a=e[i].a,b=e[i].b,faa=getf(a),fab=getf(b);
		if(faa==fab) continue;
		ans+=e[i].w; merge(faa,fab); used[i]=true;
	}
}
int dep[N],fa[N][21],da[N][21],cida[N][21];//da存储最大值,cida存储严格次大值
void update(int &zuida,int &cida,int a){
	if(a>zuida){
		cida=zuida;
		zuida=a;
	} else if((a<zuida)&&(a>cida)) cida=a;
}
void dfs(int v,int father,int dp,int dis){
	fa[v][0]=father; dep[v]=dp; da[v][0]=dis;
	rep(i,1,20){
        fa[v][i]=fa[fa[v][i-1]][i-1];
		int da1=da[v][i-1],cida1=cida[v][i-1];
		int da2=da[fa[v][i-1]][i-1],cida2=cida[fa[v][i-1]][i-1];
		update(da[v][i],cida[v][i],da1);
		update(da[v][i],cida[v][i],da2);
		update(da[v][i],cida[v][i],cida1);
		update(da[v][i],cida[v][i],cida2);
	}
	for(int i=head[v];i!=0;i=nxt[i]){
		if(to[i]!=father) dfs(to[i],v,dp+1,w[i]);
	}
}
pair<int,int> dalu(int a,int b){//倍增求最大瓶颈路、次大瓶颈路
	if(dep[a]<dep[b]) return dalu(b,a);
	int zuida=0,nowcida=0;
	//应该先更新信息再跳到父亲 
	per(i,20,0) 
        if(dep[fa[a][i]]>=dep[b]) {
		update(zuida,nowcida,da[a][i]);
		update(zuida,nowcida,cida[a][i]);
		a=fa[a][i];
	}
	if(a==b) return make_pair(zuida,nowcida);
	per(i,20,0) if(fa[a][i]!=fa[b][i]){
		update(zuida,nowcida,da[a][i]);
		update(zuida,nowcida,cida[a][i]);
		update(zuida,nowcida,da[b][i]);
		update(zuida,nowcida,cida[b][i]);
		a=fa[a][i]; b=fa[b][i];
	}
	update(zuida,nowcida,da[a][0]);
	update(zuida,nowcida,da[b][0]);
	return make_pair(zuida,nowcida);
}
int main(){
	ios::sync_with_stdio(false); cin.tie(0); 
    //freopen("input.in","r",stdin);
	cin>>n>>m;
	rep(i,1,m) cin>>e[i].a>>e[i].b>>e[i].w;
	Kruskal();
	rep(i,1,m) if(used[i]) addedge(e[i].a,e[i].b,e[i].w),addedge(e[i].b,e[i].a,e[i].w);//建树 
	dfs(1,1,1,0);//倍增预处理
	rep(i,1,m){
		if(used[i]) continue;
		pair<int,int> ret=dalu(e[i].a,e[i].b);
		if(e[i].w==ret.first) dif=min(dif,e[i].w-ret.second);
			else dif=min(dif,e[i].w-ret.first);
	}
	//cout<<dif<<endl;
	//cout<<ans<<endl;
	cout<<ans+dif;
	return 0;
}

猜你喜欢

转载自blog.csdn.net/TengWan_Alunl/article/details/83048356