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 求出一 ...
随机推荐
- 初始C语言中的指针(翁凯男神MOOC)
运算符 & ● scanf("%d",&i); ●获得变量的地址,它的操作数必须是变量 ● int i; printf("%x",& ...
- kotlin函数api
原 Kotlin学习(4)Lambda 2017年09月26日 21:00:03 gwt0425 阅读数:551 记住Lambda的本质,还是一个对象.和JS,Python等不同的是,Kotlin ...
- linux服务器中Jenkins集成git、Gradle持续构建Springboot项目
Jenkins是用java编写的开源持续集成工具,目前被国内外各公司广泛使用.本章教大家如何在linux服务器中使用Jenkins自动发布一个可作为linux服务发布的Springboot项目. 自动 ...
- HTML5 data属性
在HTML5中添加了data-*的方式来自定义属性,所谓data-*实际上上就是data-前缀加上自定义的属性名,命名可以用驼峰命名方式,但取值是必需全部使用小写,否则是undefinde 使用这样的 ...
- node-pre-gyp install --fallback-to-build 错误
[node-pre-gyp install --fallback-to-build 错误] npm install bcrypt时遇上错误 此时,安装node-gyp npm install -g n ...
- excel表格输入思想
1.创建工作簿 SXSSFWorkbook wb = new SXSSFWorkbook(); //#设置单元格的垂直居中,水平居中,字体颜色 2.创建sheet Sheet sheet = wb ...
- cacti有图无数据解决办法
Cacti 安装不久,图像界面出来了,但是一直没有数据. Cacti 日志中的错误或警告也都一个个全部解决.有些需要访问文件的权限也都有了. 1.system utilities –>Rebui ...
- python处理数据问题详解
连接数据库 这里需要调用pymysql包,(pip install PyMySQL) 注意pip安装时名字和程序里import的名字不一样 import pymysql # 打开数据库连接 db = ...
- leetcode题库解答源码(python3)
下面和大家分享本人在leetcode上已经ace的题目源码(python3): 本人会持续更新!- class Leetcode_Solution(object): def twoSum_1(self ...
- typedef void (*Fun) (void) 的理解——函数指针——typedef函数指针
首先介绍大家比较熟悉的typedef int i;//定义一个整型变量i typedef myInt int: myInt j;//定义一个整型变量j 上面介绍得是我们常用的比较简单的typedef的 ...