【BZOJ 1977】[BeiJing2010組隊]次小生成樹 Tree

思想簡單,寫起來噁心,還好1A了(逃,多考慮一下就好了

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<vector>
#define LL long long 
#define maxn 300021
using namespace std;
vector<int>g[maxn];
vector<int>w[maxn];
int n,m,f[maxn][20],Max1[maxn][30],Max2[maxn][20],ff[maxn];
int h[maxn];
LL all,ans=1e18;
struct edge{
	int a,b,c,flag;
	bool operator<(const edge& y)const{return c<y.c;}
}e[maxn];
int find(int x){return ff[x]==x ? x : ff[x]=find(ff[x]);}
void pre(){
	scanf("%d%d",&n,&m);
	for(int i=1;i<=m;i++)scanf("%d%d%d",&e[i].a,&e[i].b,&e[i].c);
	sort(e+1,e+1+m);
	for(int i=1;i<=n;i++)ff[i]=i;
	for(int x,y,a,b,i=1;i<=m;i++){
		a=e[i].a,b=e[i].b;
		x=find(a),y=find(b);
		if(x==y)continue;
		ff[x]=y,e[i].flag=1,all+=(LL)e[i].c;
		g[a].push_back(b),g[b].push_back(a);
		w[a].push_back(e[i].c),w[b].push_back(e[i].c);
	}
}
void dfs(int u,int fa){
	f[u][0]=fa,h[u]=h[fa]+1;
	for(int v,i=1;i<=17;i++){
		v=f[u][i-1];
		f[u][i]=f[v][i-1];
		Max1[u][i]=max(Max1[u][i-1],Max1[v][i-1]);
		if(Max1[u][i-1]!=Max1[v][i-1])Max2[u][i]=min(Max1[u][i-1],Max1[v][i-1]);
		else Max2[u][i]=max(Max2[u][i-1],Max2[v][i-1]);
	}
	for(int v,i=0;i<g[u].size();i++){
		if((v=g[u][i])==fa)continue;
		Max1[v][0]=w[u][i];
		Max2[v][0]=-1e9;
		dfs(v,u);
	}
}
int lca(int a,int b){
	if(h[a]>h[b])swap(a,b);
	for(int i=17;i>=0;i--)if(h[f[b][i]]>=h[a])b=f[b][i];
	if(a==b)return a;
	for(int i=17;i>=0;i--){
		if(f[a][i]==f[b][i])continue;
		a=f[a][i],b=f[b][i];
	}return f[a][0];
}
void solve(int a,int b,int w){
	int m1=0,m2=0;
	int g=lca(a,b);
	for(int x,i=17;i>=0;i--){
		if(h[f[a][i]]<h[g])continue;
		if(Max1[a][i]>m1){
			m2=m1,m1=Max1[a][i];
			m2=max(m2,Max2[a][i]);
		}else if(Max1[a][i]==m1){
			m2=max(m2,Max2[a][i]);
		}else m2=max(m2,Max1[a][i]);
		a=f[a][i];
	}
	
	for(int x,i=17;i>=0;i--){
		if(h[f[b][i]]<h[g])continue;
		if(Max1[b][i]>m1){
			m2=m1,m1=Max1[b][i];
			m2=max(m2,Max2[b][i]);
		}else if(Max1[b][i]==m1){
			m2=max(m2,Max2[b][i]);
		}else m2=max(m2,Max1[b][i]);
		b=f[b][i];
	}
	
	if(w!=m1)
	ans=min(ans,all-m1+w);
	else ans=min(ans,all-m2+w);
}

int main(){
	pre();
	dfs(1,0);
	for(int i=1;i<=m;i++){
		if(!e[i].flag)solve(e[i].a,e[i].b,e[i].c);
	}printf("%lld",ans);
	return 0;
}


發佈了339 篇原創文章 · 獲贊 18 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章