luogu 4180 严格次小生成树
次小生成树,顾名思义和次短路的思路似乎很类似呀,
于是就先写了个kruskal(prim不会)跑出最小生成树,给所有路径打标记,再逐个跑最小生成树取大于最小生成树的最小值 50分
#include<bits/stdc++.h>
#define rep(i,x,y) for(register int i=x;i<=y;i++)
#define dec(i,x,y) for(register int i=x;i>=y;i--)
#define ll long long
using namespace std;
const int N=;
const int M=;
const int inf=0x3f3f3f3f;
inline int read(){
int x=,f=;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')f=-;ch=getchar();}
while(isdigit(ch)){x=(x<<)+(x<<)+(ch^);ch=getchar();}
return x*f;}
int n,m,u,v,w,fa[N],ok[N],k;
struct node{int u,v,w;}e[M<<];
bool cmp(node a,node b){return a.w<b.w;}
inline int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
int kruskal(){
int cnt=n,ans=;
rep(i,,n) fa[i]=i;
for(int i=;i<=m;i++){
if(cnt==) break;
if(ok[i]==){
int xx=find(e[i].u),yy=find(e[i].v);
if(xx!=yy) fa[yy]=xx,cnt--,ans+=e[i].w;}
}return ans;}
int main(){
n=read();m=read();
rep(i,,m){
u=read();v=read();w=read();
e[i]=(node){u,v,w};} sort(e+,e++m,cmp);
//ok =0代表
int ans=inf,mi=kruskal();
for(int i=;i<=m;i++){
ok[i]=;k=kruskal();
if(k>mi) ans=min(ans,k);ok[i]=;}
printf("%d\n",ans);
return ;
}
100分(啥时候得再复习一下,不看题解不会做系列,ganxiehzwercode,啥时候再拿出来重新写一写)
对于非最小生成树上的路径,其u,v加入后(可能)形成一个环,分别从u.v到lca寻找最大及次大路径,若最大路径不等于(其实就是小于)非生成树边,记录这个最小增量,
相等则取次小边,防止出现 次小==最小
#include<bits/stdc++.h>
#define rep(i,x,y) for(register int i=x;i<=y;i++)
#define N 100001
#define M 300001
#define inf 0x7fffffff
#define ll long long
using namespace std;
int n,m,tot,cnt,mn=inf;ll ans;
int f[N],head[N],dep[N],fa[N][],d1[N][],d2[N][];
struct data{int x,y,v;bool sel;}a[M];
struct edge{int to,next,v;}e[N<<];
bool cmp(data a,data b){return a.v<b.v;}
void insert(int u,int v,int w){
e[++cnt].to=v;e[cnt].next=head[u];e[cnt].v=w;head[u]=cnt;
e[++cnt].to=u;e[cnt].next=head[v];e[cnt].v=w;head[v]=cnt;}
inline int find(int x){return x==f[x]?x:f[x]=find(f[x]);}
void dfs(int u,int f){
for(int i=;i<=;i++){
if(dep[u]<(<<i))break;
fa[u][i]=fa[fa[u][i-]][i-];
d1[u][i]=max(d1[u][i-],d1[fa[u][i-]][i-]);
if(d1[u][i-]==d1[fa[u][i-]][i-])
d2[u][i]=max(d2[u][i-],d2[fa[u][i-]][i-]);
else d2[u][i]=min(d1[u][i-],d1[fa[u][i-]][i-]),
d2[u][i]=max(d2[u][i],max(d2[u][i-],d2[fa[u][i-]][i-]));
}for(int i=head[u];i;i=e[i].next){
int v=e[i].to;
if(v==f) continue;
fa[v][]=u;
d1[v][]=e[i].v;
dep[v]=dep[u]+;
dfs(v,u);
}
}
int lca(int x,int y){
if(dep[x]<dep[y])swap(x,y);
int t=dep[x]-dep[y];
for(int i=;i<=;i++)
if((<<i)&t)x=fa[x][i];
for(int i=;i>=;i--)
if(fa[x][i]!=fa[y][i])
x=fa[x][i],y=fa[y][i]; if(x==y)return x;
return fa[x][];}
void cal(int x,int f,int v){
int mx1=,mx2=;
int t=dep[x]-dep[f];
for(int i=;i<=;i++)
if(t&(<<i)){
if(d1[x][i]>mx1){
mx2=mx1;
mx1=d1[x][i];}
mx2=max(mx2,d2[x][i]);
x=fa[x][i];
}
if(mx1!=v)mn=min(mn,v-mx1);
else mn=min(mn,v-mx2);}
void solve(int t,int v){
int x=a[t].x,y=a[t].y,f=lca(x,y);
cal(x,f,v);cal(y,f,v);}
int main(){
scanf("%d%d",&n,&m);
rep(i,,n) f[i]=i;
rep(i,,m) scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].v);
sort(a+,a+m+,cmp);
rep(i,,m){
int xx=find(a[i].x),yy=find(a[i].y);
if(xx!=yy){
f[xx]=yy;
ans+=a[i].v;
a[i].sel=;
insert(a[i].x,a[i].y,a[i].v);
tot++;if(tot==n-)break;}
}dfs(,);
rep(i,,m) if(!a[i].sel)solve(i,a[i].v);
printf("%lld",ans+mn);
return ;
}
luogu 4180 严格次小生成树的更多相关文章
- 【luogu P4180 严格次小生成树[BJWC2010]】 模板
题目链接:https://www.luogu.org/problemnew/show/P4180 这个题卡树剖.记得开O2. 这个题inf要到1e18. 定理:次小生成树和最小生成树差距只有在一条边上 ...
- 洛谷.4180.[模板]次小生成树Tree(Kruskal LCA 倍增)
题目链接 构建完MST后,枚举非树边(u,v,w),在树上u->v的路径中找一条权值最大的边(权为maxn),替换掉它 这样在 w=maxn 时显然不能满足严格次小.但是这个w可以替换掉树上严格 ...
- BZOJ1977或洛谷4180 [BJWC2010]次小生成树
一道LCA+生成树 BZOJ原题链接 洛谷原题链接 细节挺多,我调了半天..累炸.. 回到正题,我们先求出随便一棵最小生成树(设边权和为\(s\)),然后扫描剩下所有边,设扫到的边的两端点为\(x,y ...
- [Luogu] 次小生成树
https://www.luogu.org/problemnew/show/P4180#sub 严格次小生成树,即不等于最小生成树中的边权之和最小的生成树 首先求出最小生成树,然后枚举所有不在最小生成 ...
- [Luogu P4180][BJWC 2010]严格次小生成树
严格次小生成树,关键是“严格”,如果是不严格的其实只需要枚举每条不在最小生成树的边,如果得到边权和大于等于最小生成树的结束就行.原理就是因为Kruskal非常贪心,只要随便改一条边就能得到一个非严格的 ...
- 【洛谷】4180:【模板】严格次小生成树[BJWC2010]【链剖】【线段树维护最大、严格次大值】
P4180 [模板]严格次小生成树[BJWC2010] 题目描述 小C最近学了很多最小生成树的算法,Prim算法.Kurskal算法.消圈算法等等.正当小C洋洋得意之时,小P又来泼小C冷水了.小P说, ...
- Luogu P4180 【模板】严格次小生成树[BJWC2010]
P4180 [模板]严格次小生成树[BJWC2010] 题意 题目描述 小\(C\)最近学了很多最小生成树的算法,\(Prim\)算法.\(Kurskal\)算法.消圈算法等等.正当小\(C\)洋洋得 ...
- 洛谷 P 4180 次小生成树
题目描述 小C最近学了很多最小生成树的算法,Prim算法.Kurskal算法.消圈算法等等.正当小C洋洋得意之时,小P又来泼小C冷水了.小P说,让小C求出一个无向图的次小生成树,而且这个次小生成树还得 ...
- 严格次小生成树(Bzoj1977:[Beijing2010组队]次小生成树)
非严格次小生成树 很简单,先做最小生成树 然后枚举没加入的边加入,替换掉这个环内最大的边 最后取\(min\) 严格次小生成树 还是一样的 可以考虑维护一个严格次大值 最大值和枚举的边相同就替换次大值 ...
随机推荐
- BZOJ3133[Baltic2013]ballmachine
题目描述 https://www.lydsy.com/JudgeOnline/problem.php?id=3133 题解 还是分两个操作来说吧. 先看第一个操作,放球,可以发现,对于祖先节点和后代节 ...
- BZOJ2244 拦截导弹
此题最早看到是在我还什么都不会的去年的暑期集训,是V8讲的DP专题,我当时还跑去问这概率怎么做.这道题要求的是二维最长不上升子序列,加上位置一维就成了三维偏序问题,也就是套用CDQ分治,对位置排序,然 ...
- Java线程池中submit()和execute之间的区别?
一: submit()方法,可以提供Future < T > 类型的返回值. executor()方法,无返回值. execute无返回值 public void execute(Runn ...
- configure: error: no acceptable C compiler found in $PATH 问题解决
解决办法: 安装GCC软件套件 [root@localhost ~]# yum install gccLoaded plugins: fastestmirrorLoading mirror speed ...
- 既然写CSS很容易,那为什么大家还是把CSS写的那么烂呢?
在众成翻译上看到一篇不错的css文章,所以就给转过来. 在你开始阅读这篇文章之前,一定要做好心理准备.因为我写的 90% 都是在发牢骚,只有最后大概 10% 介绍 CSS 技巧之最佳实践.提前给你们打 ...
- 【洛谷P1164 小A点菜】
题目背景 uim神犇拿到了uoi的ra(镭牌)后,立刻拉着基友小A到了一家……餐馆,很低端的那种. uim指着墙上的价目表(太低级了没有菜单),说:“随便点”. 题目描述 不过uim由于买了一些辅(e ...
- 第三十七篇-BottomNavigationVIew底部导航的使用
效果图: 添加底部导航和viewpaper 设置底部导航在底部 app:layout_constraintBottom_toBottomOf="parent" 新建四个fragme ...
- c#中序列化和反序列化的理解
using System.IO;using System.Runtime.Serialization.Formatters.Binary; 序列化:对象转化为文件的过程(字节流) 反序列化:文件(字节 ...
- hystrix实战之javanica
spingboot2.0.3集成hystrix的,访问dashboard的另外一种方式: https://blog.csdn.net/qq_38455201/article/details/80783 ...
- 构造方法中关键字-- super
package lijun.cn.demo4; public class Person { int num =777; public Person(){ System.out.println(&quo ...