好吧我太菜了又调了一晚上。。。QAQ


先跑出最小生成树,标记树边,再用树上倍增的思路,预处理出:

  f[u][i] :距离u为2^i的祖先

  h[u][i][0/1] :距u点在2^i范围内的最长边和次长边

然后枚举每一条非树边(u,v),会与原先的最小生成树构成一个环,而之前预处理出的数据可以快速找到(u,v)在最小生成树上的最大和次大边,来更新答案

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
#define int long long
#define R register int
using namespace std;
inline int g() {
R ret=,fix=;register char ch; while(!isdigit(ch=getchar())) fix=ch=='-'?-:fix;
do ret=ret*+(ch^); while(isdigit(ch=getchar())); return ret*fix;
}
struct node{int u,v,w;bool operator <(const node & y) const { return w<y.w;}}a[];
struct edge{int v,w,nxt;}e[];
int n,m,cnt,mx,mmx,mn=0x3f3f3f3f,ans,tot;
int fir[],f[][],h[][][],fa[],d[];
bool tr[];
inline void add(int u,int v,int w) {e[++cnt].v=v,e[cnt].nxt=fir[u],e[cnt].w=w,fir[u]=cnt;}
inline void ins(int u,int v,int w) {add(u,v,w),add(v,u,w);}
inline int getf(int x) {return x==fa[x]?x:fa[x]=getf(fa[x]);}
inline void dfs(int u,int fa) {
for(R i=fir[u];i;i=e[i].nxt) {
R v=e[i].v; if(v==fa) continue;
f[v][]=u,h[v][][]=e[i].w,d[v]=d[u]+;
for(R i=;d[v]>=(<<i);++i) {
f[v][i]=f[f[v][i-]][i-];
h[v][i][]=max(h[v][i-][],h[f[v][i-]][i-][]);
if(h[v][i-][]==h[f[v][i-]][i-][])
h[v][i][]=max(h[v][i-][],h[f[v][i-]][i-][]);
else {
h[v][i][]=min(h[v][i-][],h[f[v][i-]][i-][]);
h[v][i][]=max(h[v][i-][],h[v][i][]);
h[v][i][]=max(h[v][i][],h[f[v][i-]][i-][]);
}
} dfs(v,u);
}
}
inline int lca(int u,int v) {
if(d[u]<d[v]) swap(u,v); R lim=log2(d[u])+;
for(R j=lim;j>=;--j) if(d[f[u][j]]>=d[v]) u=f[u][j];
if(u==v) return u;
for(R j=lim;j>=;--j) if(f[u][j]!=f[v][j]) u=f[u][j],v=f[v][j];
return f[u][];
}
inline void calc(int u,int fa,int w) {
mx=,mmx=; R lim=log2(d[u]-d[fa])+;
for(R i=lim;i>=;--i) if(d[u]-d[fa]>=(<<i)){
if(h[u][i][]>mx) mmx=mx,mx=h[u][i][];
mx=max(h[u][i][],mx); mmx=max(mmx,h[u][i][]),u=f[u][i];
}
if(mx!=w) mn=min(mn,w-mx); else mn=min(mn,w-mmx);
}
signed main() {
n=g(),m=g();
for(R i=;i<=n;++i) fa[i]=i;
for(R i=;i<=m;++i) a[i].u=g(),a[i].v=g(),a[i].w=g();
sort(a+,a+m+);
for(R i=;i<=m&&tot<n;++i) {
R uf=getf(a[i].u),vf=getf(a[i].v);
if(uf==vf) continue;
fa[uf]=vf; ans+=a[i].w; tr[i]=true;
ins(a[i].u,a[i].v,a[i].w); ++tot;
} dfs(,);
for(R i=;i<=m;++i) if(!tr[i]) {
R L=lca(a[i].u,a[i].v);
calc(a[i].u,L,a[i].w); calc(a[i].v,L,a[i].w);
} printf("%lld\n",ans+mn);
}

2019.04.09

最新文章

  1. 针对JS经典题型对全局变量及局部变量的理解浅谈
  2. 在Ubuntu 64位OS上运行hadoop2.2.0[重新编译hadoop]
  3. UVA 1351 十三 String Compression
  4. linux监控nmon和analyser的使用
  5. 我的第一个python爬虫程序
  6. Html的maxlength属性
  7. Fantageek翻译系列之《使用Autolayout显示变化高度的UITableViewCell》
  8. 数据结构C语言版 弗洛伊德算法实现
  9. 输出无名空数组---精android、IOS App应用服务程序开发
  10. Zend Server更新至6.2版本——虚拟主机全方位管理
  11. MongoDB数据库索引构建情况分析
  12. 使用SuperSocket打造逾10万长连接的Socket服务
  13. 外部 Storage Provider - 每天5分钟玩转 Docker 容器技术(149)
  14. MyBatis 学习总结 01 快速入门
  15. BZOJ1066 [SCOI2007]蜥蜴 网络流 最大流 SAP
  16. C++ 字面量
  17. 使用Vagrant和VirtualBox一步步地创建一个Base Box
  18. 聊一聊 Spring 中的线程安全性
  19. jsp页面编写锚点,和html页面编写锚点
  20. P4514 上帝造题的七分钟

热门文章

  1. nginx日志输出参数记录
  2. Linux bash shell环境变量以及语法规范
  3. 2017 google IO大会——5.17
  4. Workerman安装流程
  5. linux 网络编程 inet_pton &amp; inet_ntop函数
  6. linux 多线程编程-读写者问题
  7. OpenCV——PS 滤镜算法之极坐标变换到平面坐标
  8. RTSP协议
  9. 【Matlab】常用函数
  10. python3 + selenium + eclipse 中报:Unable to find a matching set of capabilities