BZOJ 1977 次小生成树(最近公共祖先)
题意:求一棵树的严格次小生成树,即权值严格大于最小生成树且权值最小的生成树。
先求最小生成树,对于每个不在树中的边,取两点间路径的信息,如果这条边的权值等于路径中的权值最大值,那就删掉路径中的次大值,加上这条非树边,更新答案;否则删掉路径中的最大值,加上这条非树边,更新答案。
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
#define ll long long
struct edge{
int u,v,id;
ll w;
}e[];
int tot,go[],first[],next[];
ll val[];
int fa[][],deep[],F[],bin[],n,m;
ll mx1[][],mx2[][],ans1,ans2;
int read(){
char ch=getchar();int t=,f=;
while (ch<''||ch>''){if (ch=='-') f=-;ch=getchar();}
while (''<=ch&&ch<=''){t=t*+ch-'';ch=getchar();}
return t*f;
}
ll Read(){
char ch=getchar();ll t=,f=;
while (ch<''||ch>''){if (ch=='-') f=-;ch=getchar();}
while (''<=ch&&ch<=''){t=t*+ch-'';ch=getchar();}
return t*f;
}
bool cmp(edge a,edge b){
return a.w<b.w;
}
void insert(int x,int y,ll z){
tot++;
go[tot]=y;
next[tot]=first[x];
first[x]=tot;
val[tot]=z;
}
void add(int x,int y,int z){
insert(x,y,z);insert(y,x,z);
}
int find(int x){
if (F[x]==x) return x;
else return (find(F[x]));
}
void up(ll x,ll &y){
if (x>y) y=x;
}
void work(int x,int i){
mx1[x][i]=std::max(mx1[fa[x][i-]][i-],mx1[x][i-]);
if (mx1[fa[x][i-]][i-]<mx1[x][i]) up(mx1[fa[x][i-]][i-],mx2[x][i]);
if (mx1[x][i-]<mx1[x][i]) up(mx1[x][i-],mx2[x][i]);
up(mx2[x][i-],mx2[x][i]);
up(mx2[fa[x][i-]][i-],mx2[x][i]);
}
void dfs(int x,int f){
for (int i=;i<=;i++)
fa[x][i]=fa[fa[x][i-]][i-],work(x,i);
for (int i=first[x];i;i=next[i]){
int pur=go[i];
if (pur==f) continue;
deep[pur]=deep[x]+;
fa[pur][]=x;
mx1[pur][]=val[i];
mx2[pur][]=;
dfs(pur,x);
}
}
void up(ll x,ll &a,ll &b){
if (x>a) b=a,a=x;
else
if (x>b&&x<a) b=x;
}
void lca(int x,int y){
ans1=,ans2=;
if (deep[x]<deep[y]) std::swap(x,y);
int t=deep[x]-deep[y];
for (int i=;i<=;i++)
if (t&bin[i]) {
up(mx1[x][i],ans1,ans2);
up(mx2[x][i],ans1,ans2);
x=fa[x][i];
}
for (int i=;i>=;i--)
if (fa[x][i]!=fa[y][i]) {
up(mx1[x][i],ans1,ans2);
up(mx2[x][i],ans1,ans2);
up(mx1[y][i],ans1,ans2);
up(mx2[y][i],ans1,ans2);
x=fa[x][i];
y=fa[y][i];
}
if (x!=y){
up(mx1[x][],ans1,ans2);
up(mx2[x][],ans1,ans2);
up(mx1[y][],ans1,ans2);
up(mx2[y][],ans1,ans2);
}
}
int main(){
bin[]=;
for (int i=;i<=;i++) bin[i]=bin[i-]*;
n=read();m=read();
for (int i=;i<=m;i++){
e[i].u=read();
e[i].v=read();
e[i].w=Read();
e[i].id=;
}
for (int i=;i<=n;i++)
for (int j=;j<=;j++)
mx1[i][j]=mx2[i][j]=;
std::sort(e+,e++m,cmp);
ll sum=;
for (int i=;i<=n;i++) F[i]=i;
for (int i=;i<=m;i++)
if (find(e[i].u)!=find(e[i].v)){
F[find(e[i].u)]=find(e[i].v);
e[i].id=;
add(e[i].u,e[i].v,e[i].w);
sum+=e[i].w;
}
dfs(,);
ll Ans=10000000000000000LL;
for (int i=;i<=m;i++)
if (!e[i].id){
lca(e[i].u,e[i].v);
if (e[i].w==ans1) Ans=std::min(Ans,sum-ans2+e[i].w);
else Ans=std::min(Ans,sum-ans1+e[i].w);
}
printf("%lld\n",Ans);
}
BZOJ 1977 次小生成树(最近公共祖先)的更多相关文章
- [BeiJing2010组队][BZOJ 1977]次小生成树 Tree
话说这个[BeiJing2010组队]是个什喵玩意? 这是一道严格次小生成树,而次小生成树的做法是层出不穷的 MATO IS NO.1 的博客里对两种算法都有很好的解释,值得拥有: (果然除我以外, ...
- BZOJ 1977 次小生成树
TM终于过了.... #include<iostream> #include<cstdio> #include<cstring> #include<algor ...
- BZOJ 1977: [BeiJing2010组队]次小生成树 Tree( MST + 树链剖分 + RMQ )
做一次MST, 枚举不在最小生成树上的每一条边(u,v), 然后加上这条边, 删掉(u,v)上的最大边(或严格次大边), 更新答案. 树链剖分然后ST维护最大值和严格次大值..倍增也是可以的... - ...
- BZOJ 1977 严格次小生成树(算竞进阶习题)
树上倍增+kruskal 要找严格次小生成树,肯定先要找到最小生成树. 我们先把最小生成树的边找出来建树,然后依次枚举非树边,容易想到一种方式: 对于每条非树边(u,v),他会与树上的两个点构成环,我 ...
- BZOJ 1977[BeiJing2010组队]次小生成树 Tree - 生成树
描述: 就是求一个次小生成树的边权和 传送门 题解 我们先构造一个最小生成树, 把树上的边记录下来. 然后再枚举每条非树边(u, v, val),在树上找出u 到v 路径上的最小边$g_0$ 和 严格 ...
- 【刷题】BZOJ 1977 [BeiJing2010组队]次小生成树 Tree
Description 小 C 最近学了很多最小生成树的算法,Prim 算法.Kurskal 算法.消圈算法等等. 正当小 C 洋洋得意之时,小 P 又来泼小 C 冷水了.小 P 说,让小 C 求出一 ...
- BZOJ 1977 严格次小生成树
小C最近学了很多最小生成树的算法,Prim算法.Kurskal算法.消圈算法等等.正当小C洋洋得意之时,小P又来泼小C冷水了.小P说,让小C求出一个无向图的次小生成树,而且这个次小生成树还得是严格次小 ...
- bzoj 1977 洛谷P4180 严格次小生成树
Description: 给定一张N个节点M条边的无向图,求该图的严格次小生成树.设最小生成树边权之和为sum,那么严格次小生成树就是边权之和大于sum的最小的一个 Input: 第一行包含两个整数N ...
- 1977: [BeiJing2010组队]次小生成树 Tree
1977: [BeiJing2010组队]次小生成树 Tree https://lydsy.com/JudgeOnline/problem.php?id=1977 题意: 求严格次小生成树,即边权和不 ...
随机推荐
- Win8/8.1/10获得完整管理员权限的方法
WIN+R,运行对话框中输入gpedit.msc,开启组策略,然后一步步地在“计算机配置”-“Windows 设置”-“安全设置”-“本地策略”-“安全选项”,找到右侧的“用户账户控制:以管理员批准模 ...
- 对C标准中空白字符(空格、回车符(\r)、换行符(\n)、水平制表符(\t)、垂直制表符(\v)、换页符(\f))的理解
版权声明:本文为博主原创文章,未经博主允许不得转载. 目录(?)[+] C标准库里<ctype.h>中声明了一个函数: int isspace(int c); 该函数判断字符c是否 ...
- UVA11922--Permutation Transformer (伸展树Splay)
题意:m条操作指令,对于指令 a b 表示取出第a~b个元素,翻转后添加到排列的尾部. 水题卡了一个小时,一直过不了样例. 原来是 dfs输出的时候 忘记向下传递标记了. #include < ...
- URAL 1658
题目大意:求出T个最小的满足各个位的和为S1,平方和为S2的数.按顺序输出.数的位数大于100或者不存在这样一个数时,输出:No solution. KB 64bit IO Format:%I ...
- (转)iOS Wow体验 - 第一章 - iOS人机界面设计规范纵览
本文是<iOS Wow Factor:Apps and UX Design Techniques for iPhone and iPad>第一章译文精选,其余章节将陆续放出. 关于本套译文 ...
- QiniuUpload- 一个方便用七牛做图床然后插入markdown的小工具
最近一段时间有用markdown做笔记,其他都好,但是markdown插入图片挺麻烦的,特别是想截图之后直接插入的时候.需要首先把图片保存了,然后还要上传到一个地方生成链接才能插入.如果有个工具可以直 ...
- CocoaPods的一些理解
在这片博客中,我将分享我从cocopods中学到的东西. 如果你使用Cocoapods,你的.gitignore文件中会有什么. 这个问题在debate on SO中被提及,但是我建议只追踪Podfi ...
- css布局详解(二)——标准流布局(Nomal flow)
css标准流布局(Nomal flow) 一.正常流 这是指西方语言中文本从左向右,从上向下显示,这也是我们熟悉的传统的HTML文档中的文本布局.注意,在非西方的语言中,流方向可能不同.大多数元素都在 ...
- Mac_配置adb环境变量
1.打开终端Terminal. 2.进入HOME目录:命令行输入 echo(这之间有一个空格) $HOME 3.创建.bash_profile文件:命令行输入 touch(这之间有一个空格).bash ...
- 利用“参数赋值”防范SQL注入漏洞攻击
<<年轻,无权享受>————送给每一个看到此文的同僚们 在这无精打采的炎夏 我躺在阳台上房东的旧沙发 回想几个月来遇到的问题 我不禁内心开始慌张喘着粗气 还有大把时间去打拼 没有到只 ...