bzoj1977 次小生成树
Description
小 C 最近学了很多最小生成树的算法,Prim 算法、Kurskal 算法、消圈算法等等。 正当小 C 洋洋得意之时,小 P 又来泼小 C 冷水了。小 P 说,让小 C 求出一个无向图的次小生成树,而且这个次小生成树还得是严格次小的,也就是说: 如果最小生成树选择的边集是 EM,严格次小生成树选择的边集是 ES,那么需要满足:(value(e) 表示边 e的权值) 这下小 C 蒙了,他找到了你,希望你帮他解决这个问题。
Input
第一行包含两个整数N 和M,表示无向图的点数与边数。 接下来 M行,每行 3个数x y z 表示,点 x 和点y之间有一条边,边的权值为z。
Output
包含一行,仅一个数,表示严格次小生成树的边权和。(数据保证必定存在严格次小生成树)
Sample Input
1 2 1
1 3 2
2 4 3
3 5 4
3 4 3
4 5 6
Sample Output
HINT
数据中无向图无自环; 50% 的数据N≤2 000 M≤3 000; 80% 的数据N≤50 000 M≤100 000; 100% 的数据N≤100 000 M≤300 000 ,边权值非负且不超过 10^9 。
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <queue>
#define REP(i,k,n) for(int i=k;i<=n;i++)
#define in(a) a=read()
#define MAXN 100010
using namespace std;
inline int read(){
int x=,f=;
char ch=getchar();
for(;!isdigit(ch);ch=getchar())
if(ch=='-')
f=-;
for(;isdigit(ch);ch=getchar())
x=x*+ch-'';
return x*f;
}
queue <int> Q;
long long sum=,ans=(1ll<<);
int n,m;
int cnt,book[MAXN<<],f[MAXN];
int vis[MAXN],depth[MAXN],tree[MAXN][],maxx[MAXN][],maxn[MAXN][];
int total=,head[MAXN],to[MAXN<<],nxt[MAXN<<],val[MAXN<<];
struct node{
int x,y,z;
}l[MAXN<<];
bool cmp(node a,node b){
return a.z<b.z;
}
inline int getf(int k){
if(f[k]==k) return k;
return f[k]=getf(f[k]);
}
inline void adl(int a,int b,int c){
total++;
to[total]=b;
val[total]=c;
nxt[total]=head[a];
head[a]=total;
return ;
}
inline void BFS(){//预处理
Q.push();
depth[]=;
vis[]=;
while(!Q.empty()){
int u=Q.front();
Q.pop();
REP(j,,){
tree[u][j]=tree[tree[u][j-]][j-];
if(maxx[u][j-]>maxx[tree[u][j-]][j-]){
maxx[u][j]=maxx[u][j-];
maxn[u][j]=max(maxx[tree[u][j-]][j-],maxn[u][j-]);
}
if(maxx[u][j-]<maxx[tree[u][j-]][j-]){
maxx[u][j]=maxx[tree[u][j-]][j-];
maxn[u][j]=max(maxx[u][j-],maxn[tree[u][j-]][j-]);
}
if(maxx[u][j-]==maxx[tree[u][j-]][j-]){
maxx[u][j]=maxx[u][j-];
maxn[u][j]=max(maxn[u][j-],maxn[tree[u][j-]][j-]);
}
}
for(int e=head[u];e;e=nxt[e])
if(!vis[to[e]]){
vis[to[e]]=;
depth[to[e]]=depth[u]+;
tree[to[e]][]=u;
maxx[to[e]][]=val[e];
Q.push(to[e]);
}
}
return ;
}
inline int lca(int u,int v,int c){//lca
if(depth[u]<depth[v]) swap(u,v);
int d=depth[u]-depth[v];
int ma=-;
for(int i=;(<<i)<=d;i++)//提到同一高度
if((<<i)&d){
if(maxx[u][i]==c) ma=max(ma,maxn[u][i]);
else ma=max(ma,maxx[u][i]);
u=tree[u][i];
// cout<<u<<" "<<ma<<endl;
}
if(u==v){
if(ma==-) return ;
return ma;
}
for(int i=;i>=;i--)//两点开跑
if(tree[u][i]!=tree[v][i]){
if(maxx[u][i]==c && maxx[v][i]==c)
ma=max(ma,max(maxn[u][i],maxn[v][i]));
if(maxx[u][i]==c && maxx[v][i]!=c)
ma=max(ma,max(maxn[u][i],maxx[v][i]));
if(maxx[v][i]==c && maxx[u][i]!=c)
ma=max(ma,max(maxn[v][i],maxx[u][i]));
if(maxx[u][i]!=c && maxx[v][i]!=c)
ma=max(ma,max(maxx[v][i],maxx[u][i]));
u=tree[u][i];
v=tree[v][i];
}//最后lca是他们的父亲,所以要再更新一次
if(maxx[u][]==c && maxx[v][]==c)
ma=max(ma,max(maxn[u][],maxn[v][]));
if(maxx[u][]==c && maxx[v][]!=c)
ma=max(ma,max(maxn[u][],maxx[v][]));
if(maxx[v][]==c && maxx[u][]!=c)
ma=max(ma,max(maxn[v][],maxx[u][]));
if(maxx[u][]!=c && maxx[v][]!=c)
ma=max(ma,max(maxx[v][],maxx[u][]));
return ma;
}
int main(){
in(n);in(m);
REP(i,,n) f[i]=i;
REP(i,,m){
in(l[i].x);
in(l[i].y);
in(l[i].z);
}
sort(l+,l+m+,cmp);
REP(i,,m){
int f1=getf(l[i].x),f2=getf(l[i].y);
if(f1!=f2){
cnt++;
book[i]=;
f[f2]=f1;
sum+=(long long)l[i].z;
adl(l[i].x,l[i].y,l[i].z);
adl(l[i].y,l[i].x,l[i].z);
}
if(cnt==n-) break;
}
BFS();
REP(i,,m)
if(!book[i]){//枚举所有的非树边
// cout<<l[i].x<<" "<<l[i].y<<" "<<l[i].z<<endl;
// cout<<lca(l[i].x,l[i].y,l[i].z)<<endl;
ans=min(ans,sum-(long long)lca(l[i].x,l[i].y,l[i].z)+(long long)l[i].z);
}
cout<<ans;
}
bzoj1977 次小生成树的更多相关文章
- bzoj1977次小生成树(重要)
#include<cstdio> #include<iostream> #include<cstring> #include<queue> #inclu ...
- 2018.09.15 bzoj1977:次小生成树 Tree(次小生成树+树剖)
传送门 一道比较综合的好题. 由于是求严格的次小生成树. 我们需要维护一条路径上的最小值和次小值. 其中最小值和次小值不能相同. 由于不喜欢倍增我选择了用树链剖分维护. 代码: #include< ...
- 【BZOJ1977】[BeiJing2010组队]次小生成树 Tree 最小生成树+倍增
[BZOJ1977][BeiJing2010组队]次小生成树 Tree Description 小 C 最近学了很多最小生成树的算法,Prim 算法.Kurskal 算法.消圈算法等等. 正当小 C ...
- 【次小生成树】bzoj1977 [BeiJing2010组队]次小生成树 Tree
Description 小 C 最近学了很多最小生成树的算法,Prim 算法.Kurskal 算法.消圈算法等等. 正当小 C 洋洋得意之时,小 P 又来泼小 C 冷水了.小 P 说,让小 C 求出一 ...
- 严格次小生成树(Bzoj1977:[Beijing2010组队]次小生成树)
非严格次小生成树 很简单,先做最小生成树 然后枚举没加入的边加入,替换掉这个环内最大的边 最后取\(min\) 严格次小生成树 还是一样的 可以考虑维护一个严格次大值 最大值和枚举的边相同就替换次大值 ...
- [BZOJ1977]严格次小生成树
[问题描述] 小C最近学了很多最小生成树的算法,Prim算法.Kurskal算法.消圈算法等等. 正当小C洋洋得意之时,小P又来泼小C冷水了.小P说,让小C求出一个无向图的次小生成树,而且这个次小生成 ...
- [BZOJ1977][BeiJing2010组队]次小生成树
题解: 首先要证明一个东西 没有重边的图上 次小生成树由任何一颗最小生成树替换一条边 但是我不会证啊啊啊啊啊啊啊 然后就很简单了 枚举每一条边看看能不能变 但有一个特殊情况就是,他和环上的最大值相等, ...
- 【bzoj1977】[BeiJing2010组队]次小生成树 Tree 最小生成树+权值线段树合并
题目描述 求一张图的严格次小生成树的边权和,保证存在. 输入 第一行包含两个整数N 和M,表示无向图的点数与边数. 接下来 M行,每行 3个数x y z 表示,点 x 和点y之间有一条边,边的权值为z ...
- [bzoj1977][BeiJing2010组队]次小生成树 Tree——树上倍增+lca
Brief Description 求一个无向图的严格次小生成树. Algorithm Design 考察最小生成树的生成过程.对于一个非树边而言,如果我们使用这一条非树边去替换原MST的路径上的最大 ...
随机推荐
- 深入理解Spring系列之五:BeanDefinition装载
转载 https://mp.weixin.qq.com/s/1_grvpJYe8mMIAnebMdz9Q 接上篇<深入理解Spring系列之四:BeanDefinition装载前奏曲>,进 ...
- 对RSA的认识
#没有经过专业老师的指导,所以您在阅读本文时建议参考即可. 学习视屏:https://www.youtube.com/watch?v=TqX0AHHwRYQ https://www.youtub ...
- 南邮PHP反序列化
题目如下: <?php class just4fun { var $enter; var $secret; } if (isset($_GET['pass'])) { $pass = $_GET ...
- ConcurrentHashMap分析
1.ConcurrentHashMap锁分段技术 ConcurrentHashMap使用锁分段技术,首先将数据分成一段一段地存储,然后给每一段数据配一把锁,当一 ...
- 【bzoj4293】【PA2015】Siano
如题,首先可以考虑相对大小是不变的. 那么先sort,之后每次在线段树上二分即可. #include<bits/stdc++.h> typedef long long ll; using ...
- 「caffe编译bug」 undefined reference to `boost::match_results<__gnu_cxx::__normal_iterator<char const*, std::__cxx11
CXX/LD -o .build_release/tools/test_net.binCXX/LD -o .build_release/tools/convert_annoset.binCXX/LD ...
- 《深入理解Java虚拟机》笔记--第十二章、Java内存模型与线程
主要内容:虚拟机如何实现多线程.多线程之间由于共享和竞争数据而导致的一系列问题及解决方案. Java内存模型: Java内存模型的主要目标是定义程序中各个变量的访问规则,即在虚拟机中将变量存储 ...
- TCP的状态兼谈Close_Wait和Time_Wait的状态
原文链接: http://www.2cto.com/net/201208/147485.html TCP的状态兼谈Close_Wait和Time_Wait的状态 一 TCP的状态: 1).LIST ...
- [ python ] 网络编程(1)
在本地电脑上有两个python文件 regist.py .login.py 一个注册,一个登录.这两个python一个是写用户信息,一个是读用户信息,要怎么做呢? 通过之前的知识,我们可以通过 reg ...
- vue中methods、watch、computed之间的差别对比以及适用场景
首先要说,methods,watch和computed都是以函数为基础的,但各自却都不同: 一.computer 当页面中有某些数据依赖其他数据进行变动的时候,可以使用计算属性. <p id=& ...