#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 3e5+7,M = 3e5 + 7,MM = 3e5+7;
const ll INF = 0x7ffffffffff;;
int n,m;
ll sum;
int cnt,head[MM],ver[MM],nex[MM],edge[MM];
int tree[MM],pre[N],ppre[N][23],depth[N],lg[N];
ll maxf[N][23],minf[N][23];//这两个要和ans 作比较,所以用ll
struct E{
int from,to,w;
E(){}
E(int from,int to,int w) : from(from),to(to),w(w){}
bool operator < (const E &b)const{
return w < b.w;
}
}e[M];
void add(int x,int y,int w){
ver[++cnt] = y;
nex[cnt] = head[x];
edge[cnt] = w;
head[x] = cnt;
}
int find(int x){
return x == pre[x] ? x : pre[x] = find(pre[x]);
}
void read(){
scanf("%d%d",&n,&m);
for(int i=1;i <= m;i ++)
scanf("%d%d%d",&e[i].from,&e[i].to,&e[i].w);
for(int i=0; i < N; i++)
pre[i] = i;
}
void work1(){
sort(e+1,e+m+1);
for(int i=1;i <= m;i ++){
int x = e[i].from,y = e[i].to,w = e[i].w;
int fx = find(x), fy = find(y);
if(fx != fy){
pre[fx] = fy;
sum += w;
add(x,y,w);
add(y,x,w);
tree[i] = 1;
}
}
}
void dfs(int f,int fa,int w){
depth[f] = depth[fa] + 1;
ppre[f][0] = fa;
minf[f][0] = -INF;
maxf[f][0] = w;
for(int i=1; (1<<i) <= depth[f];i++){
ppre[f][i] = ppre[ppre[f][i-1]][i-1];
maxf[f][i] = max(maxf[f][i-1],maxf[ppre[f][i-1]][i-1]);
minf[f][i] = max(minf[f][i-1],minf[ppre[f][i-1]][i-1]);//这里分清次小关系
if(maxf[f][i-1] > maxf[ppre[f][i-1]][i-1]) minf[f][i] = max(minf[f][i],maxf[ppre[f][i-1]][i-1]);
else if(maxf[f][i-1] < maxf[ppre[f][i-1]][i-1]) minf[f][i] = max(minf[f][i],maxf[f][i-1]);
}
for(int i=head[f]; i ; i=nex[i]){
int y = ver[i],w = edge[i];
if(y != fa){
dfs(y,f,w);
}
}
}
int lca(int x,int y){
if(depth[x] < depth[y]) swap(x,y);
while(depth[x] > depth[y])
x = ppre[x][lg[depth[x]-depth[y]] -1];
if(x==y) return x;
for(int i = lg[depth[x]]-1; i>=0; i--){
if(ppre[x][i] != ppre[y][i])
x= ppre[x][i],y = ppre[y][i];
}
return ppre[x][0];
}
ll qmax(int x,int y,int maxx){
ll ans = -INF;
for(int i = lg[depth[x]]-1;i>=0;i--){
if(depth[ppre[x][i]]>=depth[y]){
if(maxx != maxf[x][i]) ans = max(ans,maxf[x][i]);
else ans = max(ans,minf[x][i]);
x = ppre[x][i];
}
}
return ans;
}
void work2(){
for(int i=1;i <= n;i++)
lg[i] = lg[i-1] + (1<<lg[i-1]==i);
dfs(1,0,0);
ll ans = INF;
for(int i = 1;i <= m;i++){
if(tree[i]) continue;
int x = e[i].from,y = e[i].to,w = e[i].w;
int lc = lca(x,y);
ll maxx = qmax(x,lc,w);
ll maxv = qmax(y,lc,w);
ans = min(ans,sum-max(maxx,maxv)+w);//找到到公共父亲节点路径中最大的那条,替换到非树边。
}
printf("%lld\n",ans);
}
int main(){
read();
work1();
work2();
return 0;
}
一本通1490:秘密的牛奶运输
最新推荐文章于 2024-05-17 18:31:39 发布