bzoj1977次小生成树(重要)
#include<cstdio>
#include<iostream>
#include<cstring>
#include<queue>
#include<algorithm>
#define Maxn 300010
#define maxn 300005
using namespace std;
#define ll long long
struct edge{
int to,w,nxt;
}edge[Maxn];
int head[Maxn/],tot;
void addedge(int a,int b,int c){
edge[tot].to=b;
edge[tot].w=c;
edge[tot].nxt=head[a];
head[a]=tot++;
}
struct line{
int u,v,w;
bool operator<(const line &a)const{
return w<a.w;
}
}q[Maxn]; int vis[Maxn];
int fa[Maxn/];
int findset(int x){
return fa[x]==x?x:(fa[x]=findset(fa[x]));
}
int unionset(int a,int b){
return fa[findset(a)]=findset(b);
}
ll d[maxn],f[maxn][],dp[maxn][][];//dp[i][j][0|1]用来表示向上倍增的最大边,严格次大边
void bfs(){
queue<int>q;
q.push();
d[]=;
while(!q.empty()){
int x=q.front();q.pop();
for(int i=head[x];i!=-;i=edge[i].nxt){
int y=edge[i].to;
if(d[y])continue;
d[y]=d[x]+;
f[y][]=x;
dp[y][][]=edge[i].w;
dp[y][][]=-0x3f3f3f3f;
for(int k=;k<=;k++){
f[y][k]=f[f[y][k-]][k-];
int a=dp[y][k-][];//y向上下一半的最大值
int b=dp[y][k-][];//y向上下一半的严格次大值
int c=dp[f[y][k-]][k-][];//y向上上一半的最大值
int d=dp[f[y][k-]][k-][];//y向上上一半的严格次大值
dp[y][k][]=max(a,c);
if(a==c)dp[x][k][]=max(b,d);
else if(a>c)dp[x][k][]=max(c,b);
else if(a<c)dp[x][k][]=max(a,d);
}
q.push(y);
}
}
}
inline void calc(ll &val1,ll &val2,ll a,ll b){//更新最大和次大
if(a<=val1)val2=max(a,val2);
else val2=val1,val1=a;
}
int lca(int x,int y,int z){//处理加入(x,y,z)后的次小生成树
ll val1=-,val2=-;
if(d[x]<d[y])swap(x,y);
for(int i=;i>=;i--)
if(d[f[x][i]]>=d[y]){
calc(val1,val2,dp[x][i][],dp[x][i][]);
x=f[x][i];
}
if(x==y){
if(val1!=z)return val1;
return val2;
} for(int i=;i>=;i--)
if(f[x][i]!=f[y][i]){
calc(val1,val2,dp[x][i][],dp[x][i][]);
calc(val1,val2,dp[y][i][],dp[y][i][]);
x=f[x][i],y=f[y][i];
}
calc(val1,val2,dp[x][][],dp[x][][]);
calc(val1,val2,dp[y][][],dp[y][][]);
x=f[x][];
if(val1!=z)return val1;
else return val2;
} int main(){
int n,m;
scanf("%d%d",&n,&m);
for(int i=;i<m;i++)
scanf("%d%d%d",&q[i].u,&q[i].v,&q[i].w);
sort(q,q+m);
for(int i=;i<=n;i++) fa[i]=i;
memset(head,-,sizeof head);
memset(vis,,sizeof vis);
tot=;
int cnt=;
long long ans=;
for(int i=;i<m;i++){
int u=q[i].u,v=q[i].v;
if(findset(u)==findset(v)) continue;
unionset(u,v);
vis[i]=;
addedge(u,v,q[i].w);
addedge(v,u,q[i].w);
ans+=q[i].w;
if(++cnt==n-) break;
}
bfs();
int z=0x3f3f3f3f;
for(int i=;i<m;i++)
if(!vis[i]) {
int t=lca(q[i].u,q[i].v,q[i].w);
if(t>)z=min(z,-t+q[i].w);
}
printf("%lld\n",ans+z);
return ;
}
bzoj1977次小生成树(重要)的更多相关文章
- 2018.09.15 bzoj1977:次小生成树 Tree(次小生成树+树剖)
传送门 一道比较综合的好题. 由于是求严格的次小生成树. 我们需要维护一条路径上的最小值和次小值. 其中最小值和次小值不能相同. 由于不喜欢倍增我选择了用树链剖分维护. 代码: #include< ...
- bzoj1977 次小生成树
Description 小 C 最近学了很多最小生成树的算法,Prim 算法.Kurskal 算法.消圈算法等等. 正当小 C 洋洋得意之时,小 P 又来泼小 C 冷水了.小 P 说,让小 C 求出一 ...
- 【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的路径上的最大 ...
随机推荐
- python小练习---TCP客户端
这是python黑帽子上的起始练习,我对其中的用到的函数做了注释,以便日后便于理解. 该程序可以访问百度,返回响应信息. 另外,我注释还有一部分UDP客户端的语句,TCP和UDP对比便于记忆. # - ...
- GB GBRT XgBoost
https://blog.csdn.net/github_38414650/article/details/76061893 https://www.cnblogs.com/wxquare/p/554 ...
- C# 事务 四种事务隔离级别
http://www.zsythink.net/archives/1233 不同隔离级别的问题 脏读(Dirty Read) 一个事务处理过程里读取了另一个未提交的事务中的数据 例子: 当一个事务 ...
- 原子类型的使用&Unsafe&CAS
在项目中也经常可以见到原子类型(AtomicXXX)的使用,而且AtomicXXX常用来代替基本类型或者基本类型的包装类型,因为其可以在不加同步锁的情况下保证线程安全(只对于原子操作). 下面以Ato ...
- android java 字符串正则表达式 分离特殊字符串
Java中正则表达式的使用 在Java中,我们为了查找某个给定字符串中是否有需要查找的某个字符或者子字串.或者对字符串进行分割.或者对字符串一些字符进行替换/删除,一般会通过if-else.for 的 ...
- SpringBoot设置Session失效时间
1 #Session超时时间设置,单位是秒,默认是30分钟 2 server.session.timeout=10 然而并没有什么用,因为SpringBoot在TomcatServletWebServ ...
- awk输出单引号,双引号【转】
双引号: awk '{print "\""}' #放大:awk '{print " \" "}' 使用“”双引号把一个双引 ...
- 用函数SendARP()获取局域网计算机的MAC地址
sendARP 31 说明对方没有开机,我们的函数检测不到它, 1784 说明的给函数的最后一个参数的值是0,或你的给的值与你给的缓存区大小不符合. 如果返回31不在线,则最后一个参数指针指向的值赋值 ...
- 题解-UOJ284 快乐游戏鸡
Problem uoj 题意大意: 一棵树,点权\(w_i\),每次玩家可以在树上行走,一条边需要\(1\)的时间,只能往儿子走.每次游戏需要从\(s\)到\(t\). 玩家有一个总死亡次数,初始为\ ...
- Statically Linking freeglut
It’s possible statically link freeglut into your applications, instead of dynamically linking agains ...