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的最大边替换成 ...
随机推荐
- [CSAPP] Chapter 1 Overview of Computer
1.1 information is bits + context All computer programs are just a sequence of bits, each with a val ...
- 根据需要通过代码的方式加载js文件
var head = document.getElementsByTagName('head')[0]; var script = document.createElement('script'); ...
- CentOS7.6安装JDK(Openjdk)
安装开始: 第一步: 使用yum源安装 OpenJDK,yum install -y java-1.8.0-openjdk 第二步: 查看安装版本,java -version 运行时发现错误汇总: 错 ...
- 【iBatis】使用resultMap配置返回结果时报错“列名无效”
使用iBatis联查DEPT.EMP两张表时 采用如下结构 <resultMap id="find_departmentMap" class="com.dto.De ...
- leetcode513
/** * Definition for a binary tree node. * public class TreeNode { * public int val; * public TreeNo ...
- django初体检课程
最简便的Python web开发框架. C:\Windows\System32>E: E:\>django-admin startproject mysite E:\>cd mysi ...
- Py小技巧一:在列表,字典,集合中根据条件筛选数据
1.过滤掉列表中的某些项---列表解析 data=[1,4,2,8,5,-1] res=[] a.依次迭代列表中每一个项 for x in data: if >=0: res.append(x) ...
- 如何提高web页面的性能
1.浏览器渲染原理解析 想要提高网页的性能,首要的便是要理解浏览器渲染原理,下面关于浏览器的原理解析,我们以chrome内核webkit为例,其他内核的浏览器原理也基本大同小异,可触类旁通. 如上图所 ...
- dbcm with kubenetes
1. create consul # kcompose convert -f /root/gitSwarm/dbcm-base-managers/compose/consul.yml genetate ...
- apt 查询软件
apt-cache search percona-server apt list percona-server-server-5.6