BZOJ 1977[BeiJing2010组队]次小生成树 Tree - 生成树
描述:
就是求一个次小生成树的边权和
题解
我们先构造一个最小生成树, 把树上的边记录下来。
然后再枚举每条非树边(u, v, val),在树上找出u 到v 路径上的最小边$g_0$ 和 严格次小边 $g_1$
如果$val > g_0$就可以考虑把$g_0$ 替换成$val$ 并记录答案。
如果$val = g_0$ 就把$g_1$替换成$val$ 记录答案。
然后我们就需要快速求出树链上的最小和次小边, 需要用树上倍增求LCA类似的方法求。
定义$g[0][ i ][ j ]$ 表示从$j$ 到第 $2^i$ 辈祖先中的最小边, $g[1][ i ][ j ] $表示从$j$ 到 第$2^i$ 辈祖先中的次小边, 满足以下关系:
1: $g[0][ i ][ j ] = \max( g[0][ i - 1][ j ], g[0][ i - 1][ f[i - 1][ j ]]) $
2 :$ g[1][ i ][ j ] = \max( g[1][ i - 1][ j ], g[1][ i - 1 ][ f[i - 1][ j ]]) $ 当$g[0][i - 1][ j ] = g[0][ i - 1][ f[i - 1][ j ]] $
3: $ g[1][ i ][ j ] = \max(g[0][ i - 1][ j ], g[1][ i - 1][ f[i - 1][ j ]])$ 当$g[0][i - 1][ j ] < g[0][ i - 1][ f[i - 1][ j ]] $
4: $ g[1][ i ][ j ] = \max(g[1][ i - 1][ j ], g[0][ i - 1][ f[i - 1][ j ]])$ 当$g[0][i - 1][ j ] > g[0][ i - 1][ f[i - 1][ j ]] $
倍增求树链上的最小和次小值时同理合并
题解
#include<cstdio>
#include<cstring>
#include<algorithm>
#define rd read()
#define rep(i,a,b) for(register int i = (a); i <= (b); ++i)
#define per(i,a,b) for(register int i = (a); i >= (b); --i)
#define ll long long
using namespace std; const int N = 5e5;
const int inf = ~0U >> ; int n, m;
ll sum, ans = 1e18;
int fa[N], f[][N], g[][][N], dep[N];
int head[N], tot; struct edge {
int nxt, to, val;
}e[N << ]; struct node {
int u, v, val, mk;
}E[N << ]; inline int read() {
int X = , p = ; char c = getchar();
for(; c > '' || c < ''; c = getchar()) if(c == '-') p = -;
for(; c >= '' && c <= ''; c = getchar()) X = X * + c - '';
return X * p;
} inline void added(int u, int v, int val) {
e[++tot].to = v;
e[tot].nxt = head[u];
e[tot].val = val;
head[u] = tot;
} inline void add(int u, int v, int val) {
added(u, v, val); added(v, u, val);
} inline int fd(int x) {
return fa[x] == x ? x : fa[x] = fd(fa[x]);
} inline int cmp(const node &A, const node &B) {
return A.val < B.val;
} inline void dfs(int u) {
for(int i = head[u]; i; i = e[i].nxt) {
int nt = e[i].to;
if(nt == f[][u]) continue;
f[][nt] = u;
g[][][nt] = e[i].val;
g[][][nt] = -inf;
dep[nt] = dep[u] + ;
dfs(nt);
}
} inline void LCA(int x, int y, int &a, int &b) {
int g0, g1;
if(dep[x] < dep[y]) swap(x, y);
for(int i = ; ~i; --i) if(dep[f[i][x]] >= dep[y]) {
g0 = g[][i][x]; g1 = g[][i][x];
if(g0 == a) b = max(b, g1);
if(g0 > a) b = max(a, g1);
if(g0 < a) b = max(g0, b);
a = max(a, g0);
x = f[i][x];
}
for(int i = ; ~i; --i) if(f[i][x] != f[i][y]) {
g0 = g[][i][x]; g1 = g[][i][x];
if(g0 == a) b = max(b, g1);
if(g0 > a) b = max(a, g1);
if(g0 < a) b = max(g0, b);
a = max(a, g0); g0 = g[][i][y]; g1 = g[][i][y];
if(g0 == a) b = max(b, g1);
if(g0 > a) b = max(a, g1);
if(g0 < a) b = max(g0, b);
a = max(a, g0);
x = f[i][x]; y = f[i][y];
} g0 = g[][][x]; g1 = g[][][x];
if(g0 == a) b = max(b, g1);
if(g0 > a) b = max(a, g1);
if(g0 < a) b = max(g0, b);
a = max(a, g0); g0 = g[][][y]; g1 = g[][][y];
if(g0 == a) b = max(b, g1);
if(g0 > a) b = max(a, g1);
if(g0 < a) b = max(g0, b);
a = max(a, g0);
} int main()
{
n = rd; m = rd;
rep(i, , n) fa[i] = i;
rep(i, , m) {
int u = rd, v = rd, val = rd;
E[i].u = u; E[i].v = v; E[i].val = val; E[i].mk = ;
}
sort(E+, E++m, cmp);
rep(i, , m) {
int x = fd(E[i].u), y = fd(E[i].v);
if(x == y) continue;
sum += E[i].val;
fa[y] = x;
E[i].mk = ;
add(E[i].u, E[i].v, E[i].val);
}
dep[] = ;
dfs();
rep(i, , ) rep(j, , n) {
f[i][j] = f[i - ][f[i - ][j]];
g[][i][j] = max(g[][i - ][j], g[][i - ][f[i - ][j]]);
int tmp = -inf;
if(g[][i - ][j] == g[][i - ][f[i - ][j]]) tmp = max(g[][i - ][j], g[][i - ][f[i - ][j]]);
if(g[][i - ][j] < g[][i - ][f[i - ][j]]) tmp = max(g[][i - ][j], g[][i - ][f[i - ][j]]);
if(g[][i - ][j] > g[][i - ][f[i - ][j]]) tmp = max(g[][i - ][j], g[][i - ][f[i - ][j]]);
g[][i][j] = tmp;
}
rep(i, , m) if(!E[i].mk) {
int x = E[i].u, y = E[i].v, g0 = -inf, g1 = -inf;
LCA(x, y, g0, g1);
if(E[i].val == g0 && g1 != -inf) ans = min(ans, sum + E[i].val - g1);
if(E[i].val > g0) ans = min(ans, sum + E[i].val - g0);
}
printf("%lld\n",ans);
}
BZOJ 1977[BeiJing2010组队]次小生成树 Tree - 生成树的更多相关文章
- BZOJ 1977: [BeiJing2010组队]次小生成树 Tree( MST + 树链剖分 + RMQ )
做一次MST, 枚举不在最小生成树上的每一条边(u,v), 然后加上这条边, 删掉(u,v)上的最大边(或严格次大边), 更新答案. 树链剖分然后ST维护最大值和严格次大值..倍增也是可以的... - ...
- 【刷题】BZOJ 1977 [BeiJing2010组队]次小生成树 Tree
Description 小 C 最近学了很多最小生成树的算法,Prim 算法.Kurskal 算法.消圈算法等等. 正当小 C 洋洋得意之时,小 P 又来泼小 C 冷水了.小 P 说,让小 C 求出一 ...
- bzoj 1977 [BeiJing2010组队]次小生成树 Tree
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1977 kruscal别忘了先按边权sort.自己觉得那部分处理得还挺好的.(联想到之前某题的 ...
- BZOJ 1977: [BeiJing2010组队]次小生成树 Tree 倍增 最小生成树
好吧我太菜了又调了一晚上...QAQ 先跑出最小生成树,标记树边,再用树上倍增的思路,预处理出: f[u][i] :距离u为2^i的祖先 h[u][i][0/1] :距u点在2^i范围内的最长边和次长 ...
- 1977: [BeiJing2010组队]次小生成树 Tree
1977: [BeiJing2010组队]次小生成树 Tree https://lydsy.com/JudgeOnline/problem.php?id=1977 题意: 求严格次小生成树,即边权和不 ...
- [BeiJing2010组队]次小生成树 Tree
1977: [BeiJing2010组队]次小生成树 Tree Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 5168 Solved: 1668[S ...
- 【BZOJ1977】[BeiJing2010组队]次小生成树 Tree 最小生成树+倍增
[BZOJ1977][BeiJing2010组队]次小生成树 Tree Description 小 C 最近学了很多最小生成树的算法,Prim 算法.Kurskal 算法.消圈算法等等. 正当小 C ...
- 洛谷P4180 [Beijing2010组队]次小生成树Tree(最小生成树,LCT,主席树,倍增LCA,倍增,树链剖分)
洛谷题目传送门 %%%TPLY巨佬和ysner巨佬%%% 他们的题解 思路分析 具体思路都在各位巨佬的题解中.这题做法挺多的,我就不对每个都详细讲了,泛泛而谈吧. 大多数算法都要用kruskal把最小 ...
- 【次小生成树】bzoj1977 [BeiJing2010组队]次小生成树 Tree
Description 小 C 最近学了很多最小生成树的算法,Prim 算法.Kurskal 算法.消圈算法等等. 正当小 C 洋洋得意之时,小 P 又来泼小 C 冷水了.小 P 说,让小 C 求出一 ...
随机推荐
- Windows 10 显示中的仅更改文本大小和加粗选项
问题描述: 在Windows 10 1703 之前的版本,在控制面板-显示中,存在如下图中的图形界面设置: 系统升级到Windows 10 1703 或是Windows 10 1709 之后,不再存在 ...
- Layout两列定宽中间自适应三列布局
最容易理解的一种方法,以中间内容为主体,通过 margin 或者 padding 将两侧撑开,最后用 absolute 定位两侧 html: <div class="container ...
- js异步加载的5种方式
方案1:$(document).ready 点评: 1.需要引用jquery 2.兼容所有浏览器. 方案2:<script>标签的async="async"属性 asy ...
- 03_java基础(六)之CRUD实现
1.简单实现 package com.day01.station.dao; /** * Created by Administrator on 2018/2/1. */ import java.sql ...
- (django1.10)访问url报错Forbidden (CSRF cookie not set.): xxx
问题:页面访问时报错 Forbidden (CSRF cookie not set.): xxx 解决方法: 修改settings.py文件,注释掉 django.middleware.csr ...
- Android的框架功能说明
OkHttp网络框架 Picasso图片缓存框架 ORMLite数据库框架 GreenDao数据库框架
- 关于slavetable
slavetable有两种情况, 从表有三个要素 1.自己主键字段的idfield 2.对应主表的主键字段masterIdField 3.对应主表主键的值 模式一.MasetrEdit模式 也就是主 ...
- 六 json&pickle模块
之前我们学习过用eval内置方法可以将一个字符串转成python对象,不过,eval方法是有局限性的,对于普通的数据类型,json.loads和eval都能用,但遇到特殊类型的时候,eval就不管用了 ...
- codeforces 722D Generating Sets 【优先队列】
You are given a set Y of n distinct positive integers y1, y2, ..., yn. Set X of n distinct positive ...
- spring上下文快速获取方法
import org.springframework.beans.BeansException;import org.springframework.context.ApplicationContex ...