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\) 严格次小生成树 还是一样的 可以考虑维护一个严格次大值 最大值和枚举的边相同就替换次大值 ...
随机推荐
- ssh-key 与 git账户配置以及多账户配置,以及通信方式从https切换到ssh
参考:http://www.cnblogs.com/dubaokun/p/3550870.html 在使用git的时候,git与远程服务器是一般通过ssh传输的(也支持ftp,https),我们在管理 ...
- Jarvis OJ [XMAN]level1 write up
首先 老规矩,把软件拖到Ubuntu里checksec一下文件 然后知道了软件位数就放到IDA32里面... 熟悉的函数名... 缘真的妙不可言... 然后看了下vulnerable_function ...
- mybatis 二级缓存
Mybatis读取缓存次序: 先从二级缓存中获取数据,如果有直接获取,如果没有进行下一步: 从一级缓存中取数据,有直接获取,如果没有进行下一步: 到数据库中进行查询,并保存到一级缓存中: 当sqlSe ...
- 基于Jenkins,docker实现自动化部署(持续交互)
前言 随着业务的增长,需求也开始增多,每个需求的大小,开发周期,发布时间都不一致.基于微服务的系统架构,功能的叠加,对应的服务的数量也在增加,大小功能的快速迭代,更加要求部署的快速化,智能化.因此 ...
- Vim auto-pairs设置选项
let g:AutoPairs = {'(':')', '[':']', '{':'}',"'":"'",'"':'"'} 设置要自动配对的 ...
- A1121. Damn Single
"Damn Single (单身狗)" is the Chinese nickname for someone who is being single. You are suppo ...
- P2602 [ZJOI2010]数字计数
https://www.luogu.org/problemnew/show/P2602 数位dp #include <bits/stdc++.h> using namespace std; ...
- 第十一节、Harris角点检测原理(附源码)
OpenCV可以检测图像的主要特征,然后提取这些特征.使其成为图像描述符,这类似于人的眼睛和大脑.这些图像特征可作为图像搜索的数据库.此外,人们可以利用这些关键点将图像拼接起来,组成一个更大的图像,比 ...
- post请求中data参数的应用
一.data为参数,json是自动的把参数转换成了json格式,一般建议用json ,url是请求地址. 二,以一个网站来做解释,看登陆的请求 抓包看一下: 用在代码里面看一下: 如果不转的话,那么用 ...
- selenium自动化测试原理和设计的分享
昨天参加了公司的一个自动化测试的分享,有一些收获,记录一下. 1.主流的web端的UI自动化测试工具 基于浏览器API: selenium2.0,Watir(IE Driver) 基于JS 进行驱动: ...