[BJWC2010]严格次小生成树(LCA,最小生成树)
[BJWC2010]严格次小生成树
题目描述
小C最近学了很多最小生成树的算法,Prim算法、Kurskal算法、消圈算法等等。正当小C洋洋得意之时,小P又来泼小C冷水了。小P说,让小C求出一个无向图的次小生成树,而且这个次小生成树还得是严格次小的,也就是说:如果最小生成树选择的边集是EM,严格次小生成树选择的边集是ES,那么需要满足:(value(e)表示边e的权值) \sum_{e \in E_M}value(e)<\sum_{e \in E_S}value(e)∑e∈EMvalue(e)<∑e∈ESvalue(e)
这下小 C 蒙了,他找到了你,希望你帮他解决这个问题。
输入输出格式
输入格式:
第一行包含两个整数N 和M,表示无向图的点数与边数。 接下来 M行,每行 3个数x y z 表示,点 x 和点y之间有一条边,边的权值为z。
输出格式:
包含一行,仅一个数,表示严格次小生成树的边权和。(数据保证必定存在严格次小生成树)
输入输出样例
输入样例#1:
5 6
1 2 1
1 3 2
2 4 3
3 5 4
3 4 3
4 5 6
输出样例#1:
11
说明
数据中无向图无自环; 50% 的数据N≤2 000 M≤3 000; 80% 的数据N≤50 000 M≤100 000; 100% 的数据N≤100 000 M≤300 000 ,边权值非负且不超过 10^9 。
最开始没有看懂题目,推不出样例很懵逼,以为要满足每条边都比最小生成树小,后来才知道就是第二小的生成树就可以了...
最开始想到跑完最小生成树之后,对于每条非生成树上的边,求出两个端点路径上的最大值,突然发现好像会出现等于的情况,一脸懵逼。然后只会暴力跳,居然70???数据好水啊
最后看题解发现求出次小值即可,这种思路都想不到我真的是太菜了。
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#define lll long long
using namespace std;
lll read()
{
lll x=0,w=1;char ch=getchar();
while(ch>'9'||ch<'0') {if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
return x*w;
}
const lll N=100010;
lll n,m,cnt,ans,sum=2000000000;
lll fa[N],deep[N],head[N],l[N][20],m1[N][20],m2[N][20],vis[3*N],quan[N];
struct node{
lll x,y,v;
}f[3*N];
struct Node{
lll to,next,v;
}edge[2*N];
bool cmp(node p,node q) {return p.v<q.v;}
lll gfa(lll x){if(fa[x]==x)return x;return fa[x]=gfa(fa[x]);}
void add(lll x,lll y,lll z)
{
cnt++;edge[cnt].to=y;edge[cnt].next=head[x];edge[cnt].v=z;head[x]=cnt;
}
void kruscal()
{
lll qwe=0;sort(f+1,f+1+m,cmp);
for(lll i=1;i<=m;i++)
{
lll xx=gfa(f[i].x),yy=gfa(f[i].y);
if(xx!=yy) fa[xx]=yy,qwe++,ans+=f[i].v,add(f[i].x,f[i].y,f[i].v),add(f[i].y,f[i].x,f[i].v),vis[i]=1;
if(qwe==n-1) break;
}
}
void dfs(lll k)
{
for(lll i=head[k];i;i=edge[i].next)
{
lll v=edge[i].to;if(deep[v]) continue;
deep[v]=deep[k]+1;l[v][0]=k;m1[v][0]=edge[i].v;dfs(v);
}
}
void init()
{
for(lll i=1;i<=19;i++)
for(lll j=1;j<=n;j++)
{
l[j][i]=l[l[j][i-1]][i-1];
if(m1[j][i-1]<m1[l[j][i-1]][i-1])
m1[j][i]=m1[l[j][i-1]][i-1],m2[j][i]=max(m1[j][i-1],m2[l[j][i-1]][i-1]);
else if(m1[j][i-1]>m1[l[j][i-1]][i-1])
m1[j][i]=m1[j][i-1],m2[j][i]=max(m1[l[j][i-1]][i-1],m2[j][i-1]);
else
m1[j][i]=m1[j][i-1],m2[j][i]=max(m2[l[j][i-1]][i-1],m2[j][i-1]);
}
}
void changex(lll x,lll i,lll &qwe1,lll &qwe2)
{
if(qwe1<m1[x][i]) qwe2=max(qwe1,m2[x][i]),qwe1=m1[x][i];
else qwe2=max(qwe2,m1[x][i]);
}
void changey(lll y,lll i,lll &qwe1,lll &qwe2)
{
if(qwe1<m1[y][i]) qwe2=max(qwe1,m2[y][i]),qwe1=m1[y][i];
else qwe2=max(qwe2,m1[y][i]);
}
lll lca(lll x,lll y,lll v)
{
lll qwe1=0,qwe2=0;if(deep[x]<deep[y]) swap(x,y);
for(lll i=19;i>=0;i--)
if(deep[l[x][i]]>=deep[y])
{
changex(x,i,qwe1,qwe2);
x=l[x][i];
}
if(x==y) {if(qwe1==v)return qwe2;return qwe1;}
for(lll i=19;i>=0;i--)
if(l[x][i]!=l[y][i])
{
changex(x,i,qwe1,qwe2);changey(y,i,qwe1,qwe2);
x=l[x][i];y=l[y][i];
}
changex(x,0,qwe1,qwe2);changey(y,0,qwe1,qwe2);
if(qwe1==v)return qwe2;return qwe1;
}
int main()
{
n=read();m=read();
for(lll i=1;i<=n;i++) fa[i]=i;
for(lll i=1;i<=m;i++)
{
f[i].x=read();f[i].y=read();f[i].v=read();
}
kruscal();deep[1]=1;dfs(1);init();
for(lll i=1;i<=m;i++)
{
if(vis[i]) continue;
sum=min(sum,f[i].v-lca(f[i].x,f[i].y,f[i].v));
}
cout<<ans+sum;
}
[BJWC2010]严格次小生成树(LCA,最小生成树)的更多相关文章
- 【题解】洛谷P4180 [BJWC2010] 严格次小生成树(最小生成树+倍增求LCA)
洛谷P4180:https://www.luogu.org/problemnew/show/P4180 前言 这可以说是本蒟蒻打过最长的代码了 思路 先求出此图中的最小生成树 权值为tot 我们称这棵 ...
- P4180 [BJWC2010]严格次小生成树
P4180 [BJWC2010]严格次小生成树 P4180 题意 求出一个无向联通图的严格次小生成树.严格次小生成树的定义为边权和大于最小生成树的边权和但不存在另一棵生成树的边权和在最小生成树和严格次 ...
- 洛谷P4180 [BJWC2010]次小生成树(最小生成树,LCT,主席树,倍增LCA,倍增,树链剖分)
洛谷题目传送门 %%%TPLY巨佬和ysner巨佬%%% 他们的题解 思路分析 具体思路都在各位巨佬的题解中.这题做法挺多的,我就不对每个都详细讲了,泛泛而谈吧. 大多数算法都要用kruskal把最小 ...
- [BJWC2010] 严格次小生成树
[BJWC2010]严格次小生成树算法及模板 所谓次小生成树,即边权之和第二小的生成树,但所谓严格,就是不能和最小的那个相等. 求解严格次小生成树的方法一般有倍增和LCT两种.当然LCT那么高级的我当 ...
- 【bzoj1977】[BeiJing2010组队]次小生成树 Tree 最小生成树+权值线段树合并
题目描述 求一张图的严格次小生成树的边权和,保证存在. 输入 第一行包含两个整数N 和M,表示无向图的点数与边数. 接下来 M行,每行 3个数x y z 表示,点 x 和点y之间有一条边,边的权值为z ...
- 刷题总结——次小生成树(bzoj1977 最小生成树+倍增)
题目: Description 小 C 最近学了很多最小生成树的算法,Prim 算法.Kurskal 算法.消圈算法等等. 正当小 C 洋洋得意之时,小 P 又来泼小 C 冷水了.小 P 说,让小 C ...
- (poj)1679 The Unique MST 求最小生成树是否唯一 (求次小生成树与最小生成树是否一样)
Description Given a connected undirected graph, tell if its minimum spanning tree is unique. Definit ...
- POJ 1679 The Unique MST (次小生成树 判断最小生成树是否唯一)
题目链接 Description Given a connected undirected graph, tell if its minimum spanning tree is unique. De ...
- 【BZOJ1977】[BeiJing2010组队]次小生成树 Tree 最小生成树+倍增
[BZOJ1977][BeiJing2010组队]次小生成树 Tree Description 小 C 最近学了很多最小生成树的算法,Prim 算法.Kurskal 算法.消圈算法等等. 正当小 C ...
随机推荐
- Centos7 yum安装OpenLDAP(普通用户可以更改密码)
环境 系统版本:centos7.4 openldap版本2.4 安装和配置 安装并启动服务 安装: yum install openldap openldap-servers openldap-cli ...
- 大数据笔记(十五)——Hive的体系结构与安装配置、数据模型
一.常见的数据分析引擎 Hive:Hive是一个翻译器,一个基于Hadoop之上的数据仓库,把SQL语句翻译成一个 MapReduce程序.可以看成是Hive到MapReduce的映射器. Hive ...
- 关于c++ error : passing " "as" " discards qualifiers
http://www.cppblog.com/cppblogs/archive/2012/09/06/189749.html 今天写了一段小代码,本以为正确,但运行后,就somehow ”discar ...
- 线段树板子1(洛谷P3372)
传送 一道线段树板子(最简单的) 似乎之前在培训里写过线段树的样子?不记得了 何为线段树? 一般就是长成这样的树,树上的每个节点代表一个区间.线段树一般用于区间修改,区间查询的问题. 我们如何种写一棵 ...
- DAY 6 上午
如果不是割点,答案减少2(n-1) 如果删去割点,删去之后整个图分成多个连通块 每一个联通块的大小*其他连通块的大小之和 先求出缩点之后的树 加尽可能少的边使树变成一个边双 找出树上的所有叶子节点(度 ...
- 使用wxpy模块了解微信好友
网上看了一篇python文章,内容简单有趣,正好可以练习一下.原文连接:http://mp.weixin.qq.com/s/oI2pH8uvq4kwYqc4kLMjuA 一.环境:Windows+py ...
- 【cs231n作业笔记】一:KNN分类器
安装anaconda,下载assignment作业代码 作业代码数据集等2018版基于python3.6 下载提取码4put 本课程内容参考: cs231n官方笔记地址 贺完结!CS231n官方笔记授 ...
- LongAdder 源码分析
LongAdder LongAdder 能解决什么问题?什么时候使用 LongAdder? 1)LongAdder 内部包含一个基础值[base]和一个单元[Cell]数组. 没有竞争的情况下,要累加 ...
- python-异常处理总结
一.异常处理 在程序运行的过程中,总会遇到各种各样的错误.程序一出错就停止运行了,下面的代码就不能运行了:这时候就需要捕捉异常,通过捕捉异常,再去做对应的处理. e.g: info = { " ...
- astype()函数
1astype()函数可用于转化dateframe某一列的数据类型 如下将dateframe某列的str类型转为int,注意astype()没有replace=True的用法,想要在原数据上修改,要写 ...