AT cf17 final J Tree MST

news/2024/9/20 18:21:44/文章来源:https://www.cnblogs.com/binbin200811/p/18385587

AT cf17 final J Tree MST

考场上想出的黑题,然而写挂了……

思路

考场推出 boruvka 算法,会的直接跳过就好。

结论:一个点向另外一个点连出的最小边,一定在最小生成树上。

证明:参考 Kruskal 生成树的流程,若当前边(最小边)不在最小生成树上,表明边的两端已经在同一个连通块中。那么存在一条更小的边连接当前边的两端,又已知当前边是最小的连接两个点的边,此处产生了矛盾,故可以证明上述结论。

发现把连通块看做一个点,代入上述结论依然成立,故可得到:一个连通块向另外一个连通块连出的最小边,一定在最小生成树上。

由于一条最小边可以消除两个连通块,那么一次最少可以消除 \(\frac{t}{2}\) 个连通块(这里的 \(t\))是连通块个数,易得最多进行 \(\log n\)​ 次每个连通块找最小边的操作,该图可以形成一棵树。

对于一般图,每次遍历 \(m\) 条边,对于每个连通块求最近连通块即可。

复杂度为:\(O(m\log n)\)

一般适用于点数较少,边数较多,而又可以快速求出一个点最近的不在同一个连通块内的点的情况(即可以替代遍历 \(m\) 条边,求出连通块最近连通块的做法)。

接着我们考虑怎样快速的求出一个点最近的不在同一个连通块内的点。

这里的最近是在图上的最近,且不包括出发点本身的 \(a\) 值。

下文所述的路径长度也为图上的路径长度,且不包括出发点本身的 \(a\) 值。

考场手玩一下数据发现下述规律:

首先生成一棵树。

\(st\) 出发的最短路径为 \(st\to 12\),长度即为下图红色线段所标的边的边权和加 \(a_{12}\)

此时若某个点想要寻找最近点,若 \(st\) 在这个点最近点的路径上,那么最近点不是 \(st\) 就是 \(12\)

证明一下,因为 \(st\) 在这个点的路径上,那么可以看做是 \(st\) 到这个点的距离加上 \(st\) 到最近的一个点的距离,所以成立。

然后你就会发现,把每一次的 \(st\) 搬到点分树上,第一次是点分树的根跑一个最近点,第二次是点分树的根的儿子跑最近点……,由于不需要经过已经求过最进点的点,所以点分树上每一层只会遍历 \(n\) 个节点。

如果需要经过已经求过最近点的点可以 \(O(1)\) 出答案。

每次使用并查集判断一个点是否在同一个连通块内。如果是已经求过最近点的点(点分树上祖先),自己和其在同一个连通块那么就取其的最近点,如果不在那么就取其到其连通块内的最近点(这个肯定更优,因为第一次筛出的无限制的最近点肯定是最小的),当然也可以取其本身。

求出后直接跑 boruvka 就行。

复杂度 \(O(n\log^2n)\),常数有一点点大。

CODE

#pragma GCC optimize(1,2,3,"Ofast","inline")
#include<bits/stdc++.h>
using namespace std;#define ll long long
#define pli pair<ll,int>
#define fi first
#define se secondconst int maxn=2e5+1;struct Edge
{int tot;int head[maxn];struct edgenode{int to,nxt,w;}edge[maxn<<1];inline void add(int x,int y,int z){tot++;edge[tot].to=y;edge[tot].nxt=head[x];edge[tot].w=z;head[x]=tot;}
}T;int n,cnt;
int f[maxn],a[maxn];ll ans;pli val[maxn],use[maxn];struct node{int u,v;ll w;}E[maxn];int rt;
int siz[maxn];
bool book[maxn],cut[maxn];
vector<int>son[maxn];char *p1,*p2,buf[100000];
#define nc() (p1==p2 && (p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++)
inline int read()
{int x=0,f=1;char ch=nc();while(ch<48||ch>57){if(ch=='-')f=-1;ch=nc();}while(ch>=48&&ch<=57)x=x*10+ch-48,ch=nc();return x*f;
}
inline void W(ll x)
{if(x<0) putchar('-'),x=-x;if(x>9) W(x/10);putchar(x%10+'0');
}
inline pli Min(pli a,pli b)
{if(a.fi<b.fi) return a;else if(a.fi==b.fi&&a.se<b.se) return a;return b;
}inline int fr(int u){return f[u]==u?u:f[u]=fr(f[u]);}
inline void dfs_siz(int u)
{book[u]=true;siz[u]=1;for(int i=T.head[u];i;i=T.edge[i].nxt){int v=T.edge[i].to;if(!book[v]&&!cut[v]) dfs_siz(v),siz[u]+=siz[v];}book[u]=false;
}
inline int dfs_rt(int u,const int tot)
{book[u]=true;int ret=u;for(int i=T.head[u];i;i=T.edge[i].nxt){int v=T.edge[i].to;if(!book[v]&&!cut[v]&&(siz[v]<<1)>tot){ret=dfs_rt(v,tot);break;}}book[u]=false;return ret;
}
inline void build(int u,int f)
{dfs_siz(u);int g=dfs_rt(u,siz[u]);cut[g]=true;son[f].emplace_back(g);for(int i=T.head[g];i;i=T.edge[i].nxt){int v=T.edge[i].to;if(!cut[v]&&!book[v]) build(v,g);}rt=g;
}inline void dfs2(int u,const int f,const int ff,ll dis)
{book[u]=true;int fu=fr(u);if(fu!=ff) val[f]=Min(val[f],{dis+a[u],u});for(int i=T.head[u];i;i=T.edge[i].nxt){int v=T.edge[i].to;if(cut[v]){if(book[v]) continue;int fv=fr(v);if(fr(use[v].se)!=ff&&fv!=ff){val[f]=Min({dis+T.edge[i].w+use[v].fi,use[v].se},val[f]);}else if(use[v].se==f&&fv!=fu) val[f]=Min({dis+T.edge[i].w+a[v],v},val[f]);else if(fv==fu) val[f]=Min({dis+T.edge[i].w+val[v].fi,val[v].se},val[f]);}else if(!book[v]&&!cut[v]) dfs2(v,f,ff,dis+T.edge[i].w);}book[u]=false;
}
inline void dfs(int g)
{cut[g]=true;dfs2(g,g,fr(g),0);if(use[g].se==0) use[g]=Min(val[g],{a[g],g});for(auto v:son[g]) dfs(v);
}
int main()
{n=read();for(int i=1;i<=n;i++) a[i]=read(),f[i]=i;for(int i=1;i<n;i++){int x,y;ll w;x=read(),y=read(),w=read();T.add(x,y,w);T.add(y,x,w);}build(1,0);memset(cut,0,sizeof(cut));E[0].w=1e18;while(cnt<n-1){dfs(rt);for(int i=1;i<=n;i++){int fv=fr(i);if(E[fv].w>val[i].fi+a[i]) E[fv]={i,val[i].se,val[i].fi+a[i]};}for(int i=1;i<=n;i++){int fv=fr(E[i].v),fu=fr(E[i].u);if(E[i].w<E[0].w&&fv!=fu){ans+=E[i].w;f[fv]=fu;cnt++;}E[i]=E[0];cut[i]=0,val[i]={1e18,1e9};}}cerr<<clock();W(ans);
}

删掉 \(IO\),大概 3k。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/788747.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

EPIC Institute of Technology Round Summer 2024 (Div. 1 + Div. 2) VP记录

EPIC Institute of Technology Round Summer 2024 (Div. 1 + Div. 2) VP记录 A 一眼 \((n - 1) m + 1\)。 B 最后的数列是固定的,每个数与最后数列的数相减后,对差值求和再加上最大值即可。 C 唐诗 C 题,获得 \(3\) 发罚时。 只有一个数右边的数归零了,它才会归零。 右往左…

入职后,我发现工作内容和自己想象中的不太一致。。

2018年6月,大三暑假进行时,实习第二天上班 昨天王工跟我说最好统一开发工具用eclipse,今早我瞄到其实也有同事用idea。 eclipse还得学习,用idea算了,随便上网找个盗版的就好咯,不纠结这么多。 公司被逮到,也是公司的问题,公司没有禁止使用idea,一定就不是我的问题。一…

folium地图绘制库和报错解决

1.资源库导入pip install folium -i https://pypi.tuna.tsinghua.edu.cn/simple 2.使用时报错解决 2.1 导入 使用报错 2.2 问题解决

Java异常详解(全文干货)

介绍Throwable Throwable 是 Java 语言中所有错误与异常的超类。 Throwable 包含两个子类:Error(错误)和 Exception(异常),它们通常用于指示发生了异常情况。 Throwable 包含了其线程创建时线程执行堆栈的快照,它提供了 printStackTrace() 等接口用于获取堆栈跟踪数据等…

《2024 年最新 YouTube 转 MP3 攻略

在当今数字化时代,我们常常会遇到想要将 YouTube 上的精彩视频内容转换为 MP3 音频格式以便于随时随地收听的情况。以下为大家介绍几种最新的实用方法: **方法一:利用在线工具** youtubemp3dl- **youtubemp3dl**:特别适用于 Windows 和 Mac 操作系统,是一款出色的基于互联…

主观与客观,破除DDD凭经验魔咒

本文书接上回《学习真DDD的最佳路径》,关注公众号(老肖想当外语大佬)获取信息:最新文章更新;DDD框架源码(.NET、Java双平台);加群畅聊,建模分析、技术实现交流;视频和直播在B站。神秘的“凭经验” 一千个人眼中有一千个哈姆雷特,每个人的经历不同,认知不同,那么看…

【Linux网络编程】Reactor模式与Proactor模式

【Linux网络编程】Reactor模式与Proactor模式 Reactor模式 Reactor 模式是指主线程即 IO 处理单元只负责监听文件描述符上是否有事件发生,有则立刻将该事件通知给工作线程即逻辑单元,除此之外,主线程不做任何其它实质性的动作。读写数据,接受新的连接,以及处理客户请求均在…

2024, 是时候告别CentOS了

到了2024年, 不管你有多喜欢CentOS, 也到了该告别CentOS的时候了. 那个可能在你职业生涯中陪伴了你非常多年, 一直稳定运行的Linux系统, 在2024年后, 已经不再是你可靠的选择了. 最后一个仍然还在维护中的CentOS 7将于2024年6月底就END OF LIFE了. 这意味着, 如果你仍然继续使用…

StringBuilder和StringBuffer的区别

一 区别 StringBuilder 线程不安全 StringBuffer 线程安全,原因是它的主要方法用了syncronized关键字修饰二 分析 看源码见

[Azure Application Insights]Azure应用程序见解概述页面中workspace的link不见了?

问题描述 在Azure Application Insights 的概述页面中,可以直接点击 Workspace Link 进入到 Workspace 资源页面。但是,在下面的示例图中,Workspace Link不见了? 这是什么原因呢? 问题解答 这是因为 Workspace 的资源组发生了改变。 Application Insights 无法根据Worksa…

MYSQL索引的选型比较

MYSQL索引 前言 Mysql 作为互联网中非常热门的数据库,其底层的存储引擎和数据检索引擎的设计非常重要,尤其是 Mysql 数据的存储形式以及索引的设计,决定了 Mysql 整体的数据检索性能。 我们知道,索引的作用是做数据的快速检索,而快速检索的实现的本质是数据结构。通过不同…