首页 > 其他分享 >at_cf17final_j Tree MST 题解

at_cf17final_j Tree MST 题解

时间:2024-04-18 09:56:30浏览次数:18  
标签:rt mst int 题解 MST cf17final fa ch read

题目链接

点击打开链接

题目解法

还是挺有收获的题

解法1

完全图求 \(mst\),首先应该考虑 \(boruvka\) 算法
现在的问题转化成了求 \(O(\log n)\) 次每个点 \(x\) 到不在 \(x\) 的连通块中的点的最短边
这个可以换根 \(dp\) 求
子树内的是好求的,只要记录所有连通块的最小值和次小值即可
子树外的同理
复杂度为 \(O(n\log n)\),但细节较多,实现较为复杂(所以我没写

解法2

这个解法才是我要重点说的
求一张图的 \(mst\) 有一个 \(trick\):先把这张图分成若干个边集,每个边集求一遍 \(mst\),然后再把所有边集的 \(mst\) 中的边拎出来再做一遍 \(mst\),得到的就是原图的 \(mst\)
如何应用到这道题中?
考虑点分治
分治中心 \(rt\) 包含的边集是什么?
包含边 \((x,y)\),满足 \(x,y\) 均在 \(rt\) 的分治子树中(或 \(rt\) 自己),且 \(x,y\) 不在 \(rt\) 的同一棵子树中
这些边做 \(mst\) 得到的边是显然的
令 \(dep_x\) 为点 \(x\) 到分治中心 \(rt\) 的距离
那么在 \(mst\) 中的边即为分治区域内的所有点 到 最小的 \(dep_x+w_x\) 的 \(x\) 的边
把这些边最后做一遍 \(mst\) 即可
时间复杂度 \(O(n\log^2n)\),且细节较少

#include <bits/stdc++.h>
#define F(i,x,y) for(int i=(x);i<=(y);i++)
#define DF(i,x,y) for(int i=(x);i>=(y);i--)
#define ms(x,y) memset(x,y,sizeof(x))
#define SZ(x) (int)x.size()-1
#define all(x) x.begin(),x.end()
#define pb push_back
using namespace std;
typedef long long LL;
typedef unsigned long long ull;
typedef pair<int,int> pii;
template<typename T> void chkmax(T &x,T y){ x=max(x,y);}
template<typename T> void chkmin(T &x,T y){ x=min(x,y);}
template<typename T> void read(T &FF){
    FF=0;int RR=1;char ch=getchar();
    for(;!isdigit(ch);ch=getchar()) if(ch=='-') RR=-1;
    for(;isdigit(ch);ch=getchar()) FF=(FF<<1)+(FF<<3)+ch-48;
    FF*=RR;
}
const int N=200010;
const LL inf=1e18;
int w[N];
vector<pii> G[N];
int siz[N];bool vis[N];
typedef tuple<LL,int,int> tup;
int cnt;
tup edge[N*30];
void get_sz(int u,int fa){
    siz[u]=1;
    for(auto [v,w]:G[u]) if(v!=fa&&!vis[v]) get_sz(v,u),siz[u]+=siz[v];
}
LL dis[N],mnv;int pos;
void get_dis(int u,int fa){
    if(dis[u]+w[u]<mnv) mnv=dis[u]+w[u],pos=u;
    for(auto [v,w]:G[u]) if(v!=fa&&!vis[v]) dis[v]=dis[u]+w,get_dis(v,u);
}
void add_edge(int u,int fa){
    if(u!=pos) edge[++cnt]={w[u]+dis[u]+mnv,u,pos};
    for(auto [v,w]:G[u]) if(v!=fa&&!vis[v]) add_edge(v,u);
}
void dfz(int rt){
    get_sz(rt,0);int tot=siz[rt];
    while(true){
        bool fl=0;
        for(auto [v,w]:G[rt]) if(siz[v]<siz[rt]&&siz[v]>tot/2){ rt=v,fl=1;break;}
        if(!fl) break;
    }
    vis[rt]=1;
    dis[rt]=0,mnv=inf,get_dis(rt,0);
    add_edge(rt,0);
    for(auto [v,w]:G[rt]) if(!vis[v]) dfz(v);
}
int fa[N];
int gfa(int x){ if(x==fa[x]) return x;return fa[x]=gfa(fa[x]);}
int main(){
    int n;read(n);
    F(i,1,n) read(w[i]);
    F(i,1,n-1){
        int x,y,z;read(x),read(y),read(z);
        G[x].pb({y,z}),G[y].pb({x,z});
    }
    dfz(1);
    sort(edge+1,edge+cnt+1);
    LL ans=0;
    F(i,1,n) fa[i]=i;
    F(i,1,cnt){
        auto [z,x,y]=edge[i];
        x=gfa(x),y=gfa(y);
        if(x!=y) fa[x]=y,ans+=z;
    }
    printf("%lld\n",ans);
    return 0;
}

标签:rt,mst,int,题解,MST,cf17final,fa,ch,read
From: https://www.cnblogs.com/Farmer-djx/p/18142872

相关文章

  • POI2010CHO-Hamsters
    POI#Year2010#kmp#字符串#dp#矩阵优化dp用\(kmp\)处理两个串拼在一起最小增加的代价,然后\(dp_{i,j}\)表示选择\(i\)个最后是\(j\)的最小长度转移枚举拼接的串这个明显可以矩阵优化//Author:xiaruizeconstintN=1e5+10;intn,m;strings[N];struc......
  • mongodb启动失败问题解决
    解决办法sudochown-Rmongod:mongod/var/lib/mongochown-Rmongod:mongod/var/log/mongodb/chown-Rmongod:mongod/tmp/mongodb-27017.sock或者可以使用mongod--config/etc/mongod.conf参考:MongoDBloadsbutbreaks,returningstatus=14-AskUbuntumon......
  • AT_abc211_d [ABC211D] Number of Shortest paths 题解
    题目简述给定一张$n$个点$m$条边的无向无权图,问从$1$到$n$的最短路有多少条。题目分析设$cnt_i$表示从$1$到$i$的最短路条数,$dis_i$表示最短路。这道题可以考虑使用BFS做,对于一个点$v$,设第一次更新它的点为$u$,则它的转移应为$cnt_v\leftarrowcnt_u$并......
  • CF81C Average Score 题解
    题目简述给定一个长度为$n$的序列,在其中取出$x$个数,构成一个数列$a$,剩下的$y$个数构成数列$b$。若第$i$个数在数列$a$中,$ans_i$等于$1$,否则等于$2$,请你给出一种方案使得两数列的平均数之和最大且$ans$的字典序最小.题目分析我们先考虑$x=y$的情况,在这种情......
  • ICPC2023杭州站题解(B D E F G H J M)
    本场金牌数量较其他场多(45枚),但金牌线题数不多。五题为分水岭,五道简单题过后所有题均为金牌题,其中有四道可做,即ABEF,做出任意一道即可拿金牌。这里提供除A题以外的所有可做题的题解。ICPC2023杭州站:M:加入比当前选择的所有数大的数一定会让平均值上升,因此答案数列中,V图中的......
  • [题解][洛谷P1136] 迎接仪式
    题目描述对于一个由字母“j”和“z”组成的字符串,可以任意交换两个字符的位置不超过k次,求最多能出现多少个“jz”字串。题解动态规划题。设f[i][j][k][0/1]表示到第i位,前面交换了j个“j”,交换了k个“z”,且第i位是j(用0表示)或z(用1表示)。当j=k时即为可行解。为什么需要用第四维......
  • [题解][洛谷P1108] 低价购买
    题目描述求最长下降子序列长度,以及最长下降子序列的个数。(构成的序列一样的时候,视为同一种最长下降子序列)题解n不超过5000,n^2复杂度即可解决该问题。主要在于如何统计最长下降子序列个数。可以设数组t[i]表示以i为结尾的最长下降子序列个数,在更新f[i]的时候顺便更新。t[i]=......
  • [ABC229E] Graph Destruction 题解
    [ABC229E]GraphDestruction题解思路解析题目要求删点,而众所周知删点的代价要大于加点的代价,于是我们考虑倒着处理询问,将每一个删点改成加点,而加点时就用并查集维护连通块即可。code#include<bits/stdc++.h>usingnamespacestd;constintN=2e5+10;intn,m,fa[N];......
  • P10342 [THUSC 2019] 数列 题解
    形式化题面:求\[\sum_{l=1}^{n}\sum_{r=l}^{n}\max_{i=l}^{r}(i-l+1)\timesf(i,r)\]其中\(f(l,r)\)为\(a_l,...,a_r\)中有多少个不同的数字。注意到,除了Sub2,其余数据点都有\(\maxf\le800\),这启发我们考虑\(O(nm)\)的算法。套路地,扫描线枚举右端点,则现在只需要考虑......
  • [ABC212E] Safety Journey 题解
    [ABC212E]SafetyJourney题解思路解析首先根据题目的条件我们可以想到dp,用\(f_{i,j}\)表示走了\(i\)步,现在在\(j\)的方案数,可见转移即是\(f_{i,u}\gets\sum{f_{i-1,v}}\),这里的\(v\)表示每个与\(u\)相连的点。可见如此做时间复杂度为\(O(kn(\frac{n(n-1)}{2}-m......