BZOJ 1977 严格次小生成树
小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。
输出格式:
包含一行,仅一个数,表示严格次小生成树的边权和。(数据保证必定存在严格次小生成树)
输入输出样例
5 6
1 2 1
1 3 2
2 4 3
3 5 4
3 4 3
4 5 6
11 题解:严格次小生成树和非严格次小生成树的思想其实差不多,无非是多维护一个u->v之间的次大值
然后这显然也是能用倍增维护的
如果把最大边拆去换成新边后整棵树仍是最小生成树,那么就换次大边用,再不对就不用
这样能保证求出的一定不是最小生成树,所以是严格次小的
代码如下:
#pragma GCC optimize(3)
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define mp make_pair
#define int long long
#define pii pair<long long,long long>
using namespace std; struct node
{
int from,to,cost;
} e[];
int n,m,f[],ans,ans1,vis[],fa[][],d1[][],d2[][],deep[];
vector<pii> g[]; int cmp(node a,node b)
{
return a.cost<b.cost;
} void dfs(int now,int ff,int dep,int dis)
{
deep[now]=dep;
d1[][now]=dis;
fa[][now]=ff;
for(int i=; i<=; i++)
{
fa[i][now]=fa[i-][fa[i-][now]];
}
for(int i=; i<=; i++)
{
register int a[];
a[]=d1[i-][now];
a[]=d1[i-][fa[i-][now]];
a[]=d2[i-][now];
a[]=d2[i-][fa[i-][now]];
sort(a,a+);
d1[i][now]=a[];
d2[i][now]=a[];
}
for(int i=; i<g[now].size(); i++)
{
if(g[now][i].first==ff) continue;
dfs(g[now][i].first,now,dep+,g[now][i].second);
}
} pii get1(int u,int v)
{
int di=0ll,di2=0ll;
if(deep[u]<deep[v]) swap(u,v);
for(int i=; i>=; i--)
{
if(deep[fa[i][u]]>=deep[v])
{
register int a[];
a[]=di;
a[]=di2;
a[]=d1[i][u];
a[]=d2[i][u];
sort(a,a+);
di=a[];
di2=a[];
u=fa[i][u];
}
}
if(u==v) return mp(di,di2);
for(int i=; i>=; i--)
{
if(fa[i][u]!=fa[i][v])
{
register int a[];
a[]=di;
a[]=di2;
a[]=d1[i][u];
a[]=d1[i][v];
a[]=d2[i][u];
a[]=d2[i][v];
sort(a,a+);
di=a[];
di2=a[];
u=fa[i][u];
v=fa[i][v];
}
}
register int a[];
a[]=di;
a[]=di2;
a[]=d1[][u];
a[]=d1[][v];
a[]=d2[][u];
a[]=d2[][v];
sort(a,a+);
di=a[];
di2=a[];
return mp(di,di2);
} void init()
{
for(int i=; i<=n; i++)
{
f[i]=i;
}
} int find(int x)
{
if(f[x]==x) return x;
return f[x]=find(f[x]);
} void unity(int i,int x,int y,int cost)
{
int fx=find(x);
int fy=find(y);
if(fx==fy) return ;
ans+=cost;
f[fy]=fx;
g[x].push_back(mp(y,cost));
g[y].push_back(mp(x,cost));
vis[i]=;
} signed main()
{
scanf("%lld%lld",&n,&m);
init();
for(int i=; i<=m; i++)
{
scanf("%lld%lld%lld",&e[i].from,&e[i].to,&e[i].cost);
}
sort(e+,e+m+,cmp);
for(int i=; i<=m; i++)
{
unity(i,e[i].from,e[i].to,e[i].cost);
}
dfs(,,,);
ans1=1e16;
for(int i=; i<=m; i++)
{
if(!vis[i])
{
pii tmp=get1(e[i].from,e[i].to);
int ans2=ans-tmp.first+e[i].cost;
int ans3=ans-tmp.second+e[i].cost;
if(ans==ans2)
{
if(ans<ans3) ans1=min(ans1,ans3);
}
else
{
ans1=min(ans1,ans2);
}
}
}
printf("%lld\n",ans1);
}
BZOJ 1977 严格次小生成树的更多相关文章
- BZOJ 1977 严格次小生成树(算竞进阶习题)
树上倍增+kruskal 要找严格次小生成树,肯定先要找到最小生成树. 我们先把最小生成树的边找出来建树,然后依次枚举非树边,容易想到一种方式: 对于每条非树边(u,v),他会与树上的两个点构成环,我 ...
- BZOJ 1977: [BeiJing2010组队]次小生成树 Tree( MST + 树链剖分 + RMQ )
做一次MST, 枚举不在最小生成树上的每一条边(u,v), 然后加上这条边, 删掉(u,v)上的最大边(或严格次大边), 更新答案. 树链剖分然后ST维护最大值和严格次大值..倍增也是可以的... - ...
- [BeiJing2010组队][BZOJ 1977]次小生成树 Tree
话说这个[BeiJing2010组队]是个什喵玩意? 这是一道严格次小生成树,而次小生成树的做法是层出不穷的 MATO IS NO.1 的博客里对两种算法都有很好的解释,值得拥有: (果然除我以外, ...
- BZOJ 1977 次小生成树(最近公共祖先)
题意:求一棵树的严格次小生成树,即权值严格大于最小生成树且权值最小的生成树. 先求最小生成树,对于每个不在树中的边,取两点间路径的信息,如果这条边的权值等于路径中的权值最大值,那就删掉路径中的次大值, ...
- 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 洛谷P4180 严格次小生成树
Description: 给定一张N个节点M条边的无向图,求该图的严格次小生成树.设最小生成树边权之和为sum,那么严格次小生成树就是边权之和大于sum的最小的一个 Input: 第一行包含两个整数N ...
- 1977: [BeiJing2010组队]次小生成树 Tree
1977: [BeiJing2010组队]次小生成树 Tree https://lydsy.com/JudgeOnline/problem.php?id=1977 题意: 求严格次小生成树,即边权和不 ...
- bzoj 1977
题意:求严格的次小生成树.点n<=100000,m<=300000 思路:很容易想到先做一边最小生成树,然后枚举每条非树边(u, v, w),然后其实就是把u,v路径上小于w的最大边替换成 ...
随机推荐
- Spring源码加载过程图解(一)
最近看了一下Spring源码加载的简装版本,为了更好的理解,所以在绘图的基础上,进行了一些总结.(图画是为了理解和便于记忆Spring架构) Spring的核心是IOC(控制反转)和AOP(面向切面编 ...
- 【Oracle】安装Oracle 10gR2 For CentOS
Oracle10gR2安装安装环境项目 版本信息 备注操作系统 CentOS5.364bit Oracle数据库 Oracle10.2.0.4 64bit 硬件信 ...
- WinForm多线程+委托防止界面卡死
1.当有大量数据需要计算.显示在界面或者调用sleep函数时,容易导致界面卡死,可以采用多线程加委托的方法解决 using System; using System.Collections.Gener ...
- 读《分布式一致性原理》zookeeper运维
1.配置详解 1.1基本配置 基本参数包括clientPort,dataDir和tickTime 1.2高级配置 下面我们再来看看zookeeper中一些高级配置参数的配置实用 2.四字命令 我们曾经 ...
- ZooKeeper与仲裁模式
为了让服务器之间可以通信,服务器间需要一些联系信息.理论上,服务器可以使用多播来发现彼此,但我们想让ZooKeeper集合支持跨多个网 络而不是单个网络,这样就可以支持多个集合的情况. 为了完成这些, ...
- Linux 下VI文件乱码解决
linux在vi 模式查看文件会有乱码问题 如图: 怎么解决呢? 在vi中输入冒号 然后执行下面的命令 如果系统编码不是utf8,vi看uft8编码文件时这样用:set termencoding=ut ...
- shell 中可以for 循环的时间加减日期格式
..};do # LAST_HOUR=`date -d '-${num} hour' +%H` 不可for循环,报格式错误 LAST_HOUR=`date "+%H" -d -${ ...
- Javascript 键盘事件
window.document.onkeydown = function (e) { var evt = window.event || e;//兼容性处理 var keycode = evt.key ...
- C#关于using用法的总结
1 作为指令,引入命名空间 using 命名空间的名字,这样可以直接使用命名空间中的类型,而不必指定类型的详细命名空间. 2 作为指令,定义别名 using 别名=详细命名空间信息的具体的类型. 3 ...
- cdoj1091-秋实大哥の恋爱物语 【kmp】
http://acm.uestc.edu.cn/#/problem/show/1091 秋实大哥の恋爱物语 Time Limit: 5000/2000MS (Java/Others) Memo ...