bzoj1977
1977: [BeiJing2010组队]次小生成树 Tree
Time Limit: 10 Sec Memory Limit: 512 MB
Submit: 3001 Solved: 751
[Submit][Status][Discuss]
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 。
Source
首先我们要知道次小生成树是最小生成树删掉一条边并加上一条边,那么枚举每条边,通过倍增计算最小边和次小边,计算答案即可。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
typedef long long ll;
typedef pair<ll,ll> PII;
#define N 100010
struct edge
{
int to,nxt,w;
}e[N*];
struct edge1
{
int u,v,w;
};
vector<edge1> E;
int n,m,cnt=;
ll tot;
int head[N],father[N],dep[N],mark[N];
int fa[N][];
ll maxcost[N][];
ll max(ll x,ll y)
{
return x>y?x:y;
}
ll min(ll x,ll y)
{
return x<y?x:y;
}
bool cp(edge1 x,edge1 y)
{
return x.w<y.w;
}
void link(int u,int v,int w)
{
e[++cnt].nxt=head[u];
head[u]=cnt;
e[cnt].to=v;
e[cnt].w=w;
}
int find(int u)
{
return u==father[u]?father[u]:find(father[u]);
}
void connect(int u,int v)
{
int a=find(u);
int b=find(v);
if(a==b) return;
father[a]=b;
}
void dfs(int u,int Fa)
{
for(int i=head[u];i;i=e[i].nxt) if(e[i].to!=Fa)
{
int v=e[i].to;
dep[v]=dep[u]+;
fa[v][]=u;
maxcost[v][]=e[i].w;
dfs(v,u);
}
}
PII lca(int u,int v)
{
PII ret;
if(dep[u]<dep[v]) swap(u,v);
for(int i=;i>=;i--) if((dep[u]-dep[v])&(<<i))
{
if(maxcost[u][i]>ret.first)
{
ret.second=ret.first;
ret.first=maxcost[u][i];
}
else if(maxcost[u][i]<ret.first)
ret.second=max(ret.second,maxcost[u][i]);
u=fa[u][i];
}
if(u==v) return ret;
for(int i=;i>=;i--) if(fa[u][i]!=fa[v][i])
{
if(maxcost[u][i]>ret.first)
{
ret.second=ret.first;
ret.first=maxcost[u][i];
}
else if(maxcost[u][i]<ret.first)
ret.second=max(ret.second,maxcost[u][i]);
if(maxcost[v][i]>ret.first)
{
ret.second=ret.first;
ret.first=maxcost[v][i];
}
else if(maxcost[v][i]<ret.first)
ret.second=max(ret.second,maxcost[v][i]);
u=fa[u][i]; v=fa[v][i];
}
if(maxcost[u][]>ret.first)
{
ret.second=ret.first;
ret.first=maxcost[u][];
}
else if(maxcost[u][]<ret.first)
ret.second=max(ret.second,maxcost[u][]);
if(maxcost[v][]>ret.first)
{
ret.second=ret.first;
ret.first=maxcost[v][];
}
else if(maxcost[v][]<ret.first)
ret.second=max(ret.second,maxcost[v][]);
return ret;
}
void build()
{
for(int i=;i<=;i++)
for(int j=;j<=n;j++) if(fa[j][i-]!=-)
{
fa[j][i]=fa[fa[j][i-]][i-];
maxcost[j][i]=max(maxcost[j][i-],
maxcost[fa[j][i-]][i-]);
}
}
void kruskal()
{
sort(E.begin(),E.end(),cp);
for(int i=;i<=n;i++) father[i]=i;
for(int i=;i<E.size();i++) if(find(E[i].u)!=find(E[i].v))
{
connect(E[i].u,E[i].v);
mark[i]=;
tot+=E[i].w;
link(E[i].u,E[i].v,E[i].w);
link(E[i].v,E[i].u,E[i].w);
}
dfs(,);
build();
ll ans=(ll)(1e17);
for(int i=;i<E.size();i++) if(!mark[i])
{
PII x=lca(E[i].u,E[i].v);
if(x.first<E[i].w) ans=min(ans,tot+E[i].w-x.first);
else if(x.first==E[i].w) ans=min(ans,tot+E[i].w-x.second);
}
printf("%lld",ans);
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=;i<=m;i++)
{
int u,v,w; scanf("%d%d%d",&u,&v,&w);
edge1 x;
x.u=u; x.v=v; x.w=w;
E.push_back(x);
}
kruskal();
return ;
}
bzoj1977的更多相关文章
- 【BZOJ1977】[BeiJing2010组队]次小生成树 Tree 最小生成树+倍增
[BZOJ1977][BeiJing2010组队]次小生成树 Tree Description 小 C 最近学了很多最小生成树的算法,Prim 算法.Kurskal 算法.消圈算法等等. 正当小 C ...
- bzoj1977 [BeiJing2010组队]次小生成树 Tree
和倍增法求lca差不多,维护每个点往上跳2^i步能到达的点,以及之间的边的最大值和次大值,先求出最小生成树,对于每个非树边枚举其端点在树上的路径的最大值,如果最大值和非树边权值一样则找次大值,然后维护 ...
- 【次小生成树】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次小生成树(重要)
#include<cstdio> #include<iostream> #include<cstring> #include<queue> #inclu ...
- [BZOJ1977][BeiJing2010组队]次小生成树
题解: 首先要证明一个东西 没有重边的图上 次小生成树由任何一颗最小生成树替换一条边 但是我不会证啊啊啊啊啊啊啊 然后就很简单了 枚举每一条边看看能不能变 但有一个特殊情况就是,他和环上的最大值相等, ...
- BZOJ1977或洛谷4180 [BJWC2010]次小生成树
一道LCA+生成树 BZOJ原题链接 洛谷原题链接 细节挺多,我调了半天..累炸.. 回到正题,我们先求出随便一棵最小生成树(设边权和为\(s\)),然后扫描剩下所有边,设扫到的边的两端点为\(x,y ...
- 2018.09.15 bzoj1977:次小生成树 Tree(次小生成树+树剖)
传送门 一道比较综合的好题. 由于是求严格的次小生成树. 我们需要维护一条路径上的最小值和次小值. 其中最小值和次小值不能相同. 由于不喜欢倍增我选择了用树链剖分维护. 代码: #include< ...
随机推荐
- 10s后自动跳转
<div class="jf_register"> <h2>您好,欢迎光临<fmt:message key="b2cShowName&quo ...
- Codeforces Round #346 (Div. 2) A Round-House
A. Round House 题目链接http://codeforces.com/contest/659/problem/A Description Vasya lives in a round bu ...
- drupal7 开发自定义上传、下载模块的上传功能
关键点有两个:1.在页面上显示出上传的控件,2.代码实现文件上传到服务器的功能 一.显示控件: 先来看关键点1: 实现页面显示出上传控件, 关键代码: $form['my_file_field'] = ...
- sf中标准的分页功能介绍
世上本无事,庸人自扰之.我喜欢一个相对比较安静的环境去学习和工作,希望在一个掉一根针的声音都能够听到的环境中,但是有时候往往相反,一片嘈杂,我改变不了周围的环境,只能改变自己,其实这些都没有什么,也许 ...
- react起步
react是一个用于构建用户界面JAVASCRIPT库. react主要用于构建UI,是MVC中的V(视图). react特点 1.声明式设计 2.高效 3.灵活 4.JSX 5.组件 6.单项响应的 ...
- Linux格式化字符串
> 常用 > 详细 给定的格式FORMAT 控制着输出,解释序列如下: %% 一个文字的 % %a 当前locale 的星期名缩写(例如: 日,代表星期日) %A 当前locale 的星期 ...
- 判断浏览器是否支持html5和css3属性
本文章内容是由一个前辈写的. CSS3特有的属性moz-Transform //判断是否具有相应属性 testProps: function (props) { var i; for (i in pr ...
- a标签href跳转---传值---禁止单引号
禁止加单引号1 href传参的值 (&t_type='航班') 错误 <a href="check_apply?applyid=<?=$applyid?>&am ...
- Marble 绘制线
#include <QtGui/QApplication> #include <marble/MarbleWidget.h> #include <marble/GeoPa ...
- 一个简单的IM系统(Demo附源码)-- ESFramework 4.0 快速上手(08)
前面的文章已经介绍完了基于ESFramework/ESPlus进行二次开发的所有要点,现在,我们可以开始小试牛刀了. 本文将介绍使用ESFramework的Rapid引擎开发的两个最简单的Demo,E ...