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