P4180 严格次小生成树[BJWC2010] Kruskal,倍增
题意就是要求一个图的严格次小生成树。以前被题面吓到了没敢做,写了一下发现并不难。
既然要考虑次小我们就先考虑最小。可以感性理解到一定有一种次小生成树,可以由最小生成树删一条边再加一条边得到。我们枚举加上去的这一条边,加上去以后原\(mst\)会成为一个基环树,想让它次小就在这个环里找一条最长的边(不包含新加进去的)删掉就好。放在树上来讲,就是找到\(u\)到\(v\)路径上的最大值。这样我们就有了非严格次小生成树。
严格要怎么处理?我们需要排除新加上的边和\(u\)到\(v\)路径最长边相等的情况。仔细思考会发现可以再倍增维护一个次大长度,如果最大长度严格小于新加上边的长度就选用最大,否则就用次大。
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 100000 + 5;
const int M = 300000 + 5;
const int INF = 0x7fffffff;
const LL INFF = 0x7fffffffffffffff;
struct Graph {
int cnt, head[N];
struct Edge {int nxt, to, w;}e[N << 1];
void clear () {
cnt = -1;
memset (head, -1, sizeof (head));
}
void add_len (int u, int v, int w) {
e[++cnt] = (Edge) {head[u], v, w}; head[u] = cnt;
e[++cnt] = (Edge) {head[v], u, w}; head[v] = cnt;
}
int deep[N], pre[N][20], w1st[N][20], w2nd[N][20];
void dfs (int u, int fa) {
deep[u] = deep[fa] + 1;
for (int i = head[u]; ~i; i = e[i].nxt) {
int v = e[i].to;
if (v != fa) {
dfs (v, u);
pre[v][0] = u;
w2nd[v][0] = -INF;
w1st[v][0] = e[i].w;
}
}
}
void build (int u) {
for (int i = 1; (1 << i) <= deep[u]; ++i) {
pre[u][i] = pre[pre[u][i - 1]][i - 1];
w1st[u][i] = max (w1st[u][i - 1], w1st[pre[u][i - 1]][i - 1]);
w2nd[u][i] = max (w2nd[u][i - 1], w2nd[pre[u][i - 1]][i - 1]);
if (w1st[u][i - 1] < w1st[pre[u][i - 1]][i - 1]) {
w2nd[u][i] = max (w2nd[u][i], w1st[u][i - 1]);
}
if (w1st[u][i - 1] > w1st[pre[u][i - 1]][i - 1]) {
w2nd[u][i] = max (w2nd[u][i], w1st[pre[u][i - 1]][i - 1]);
}
}
for (int i = head[u]; ~i; i = e[i].nxt) {
if (e[i].to != pre[u][0]) build (e[i].to);
}
}
int lca (int u, int v) {
if (deep[u] < deep[v]) swap (u, v);
for (int i = 19; i >= 0; --i) {
if (deep[u] - deep[v] >= (1 << i)) {
u = pre[u][i];
}
}
if (u == v) return u;
for (int i = 19; i >= 0; --i) {
if (pre[u][i] != pre[v][i]) {
u = pre[u][i];
v = pre[v][i];
}
}
return pre[u][0];
}
int query (int u, int v, int w) {
//求u到v之间严格小于w的最大的值
int ans = -INF;
for (int i = 19; i >= 0; --i) {
if (deep[v] - deep[u] >= (1 << i)) {
if (w1st[v][i] < w) {
ans = max (ans, w1st[v][i]);
} else {
ans = max (ans, w2nd[v][i]);
}
v = pre[v][i];
}
}
return ans;
}
}G;
struct Len {
int u, v, w;
bool operator < (Len rhs) const {
return w < rhs.w;
}
Len () {}
Len (int u, int v, int w) : u(u), v(v), w(w) {}
}arr[M];
int n, m, Set[N], in_mst[M];
int find (int x) {
return x == Set[x] ? x : (Set[x] = find (Set[x]));
}
int main () {
G.clear ();
cin >> n >> m;
for (int i = 0; i < m; ++i) {
static int u, v, w;
cin >> u >> v >> w;
arr[i] = Len (u, v, w);
}
sort (arr, arr + m);
for (int i = 0; i <= n; ++i) Set[i] = i;
LL mstw = 0;
for (int i = 0; i < m; ++i) {
int u = arr[i].u;
int v = arr[i].v;
int w = arr[i].w;
if (find (u) != find (v)) {
mstw += w;
in_mst[i] = true;
G.add_len (u, v, w);
Set[find (u)] = find (v);
}
}
G.w1st[1][0] = -INF;
G.dfs (1, 0);
G.build (1);
LL ans = INFF;
for (int i = 0; i < m; ++i) {
if (!in_mst[i]) {
int u = arr[i].u;
int v = arr[i].v;
int w = arr[i].w;
int _lca = G.lca (u, v);
int maxu = G.query (_lca, u, w);
int maxv = G.query (_lca, v, w);
ans = min (ans, mstw + w - max (maxu, maxv));
}
}
cout << ans << endl;
}
P4180 严格次小生成树[BJWC2010] Kruskal,倍增的更多相关文章
- 「LuoguP4180」 【模板】严格次小生成树[BJWC2010](倍增 LCA Kruscal
题目描述 小C最近学了很多最小生成树的算法,Prim算法.Kurskal算法.消圈算法等等.正当小C洋洋得意之时,小P又来泼小C冷水了.小P说,让小C求出一个无向图的次小生成树,而且这个次小生成树还得 ...
- 【洛谷 P4180】【模板】严格次小生成树[BJWC2010](倍增)
题目链接 题意如题. 这题作为我们KS图论的T4,我直接打了个很暴力的暴力,骗了20分.. 当然,我们KS里的数据范围远不及这题. 这题我debug了整整一个晚上还没debug出来,第二天早上眼前一亮 ...
- 【luogu P4180 严格次小生成树[BJWC2010]】 模板
题目链接:https://www.luogu.org/problemnew/show/P4180 这个题卡树剖.记得开O2. 这个题inf要到1e18. 定理:次小生成树和最小生成树差距只有在一条边上 ...
- P4180-[BJWC2010]严格次小生成树【Kruskal,倍增】
正题 题目链接:https://www.luogu.com.cn/problem/P4180 题目大意 \(n\)个点\(m\)条边的一张无向图,求它的严格次小生成树. \(1\leq n\leq 1 ...
- Luogu P4180 【模板】严格次小生成树[BJWC2010]
P4180 [模板]严格次小生成树[BJWC2010] 题意 题目描述 小\(C\)最近学了很多最小生成树的算法,\(Prim\)算法.\(Kurskal\)算法.消圈算法等等.正当小\(C\)洋洋得 ...
- P4180 【模板】严格次小生成树[BJWC2010]
P4180 [模板]严格次小生成树[BJWC2010] 倍增(LCA)+最小生成树 施工队挖断学校光缆导致断网1天(大雾) 考虑直接枚举不在最小生成树上的边.但是边权可能与最小生成树上的边相等,这样删 ...
- 【洛谷】4180:【模板】严格次小生成树[BJWC2010]【链剖】【线段树维护最大、严格次大值】
P4180 [模板]严格次小生成树[BJWC2010] 题目描述 小C最近学了很多最小生成树的算法,Prim算法.Kurskal算法.消圈算法等等.正当小C洋洋得意之时,小P又来泼小C冷水了.小P说, ...
- 【题解】洛谷P4180 [BJWC2010] 严格次小生成树(最小生成树+倍增求LCA)
洛谷P4180:https://www.luogu.org/problemnew/show/P4180 前言 这可以说是本蒟蒻打过最长的代码了 思路 先求出此图中的最小生成树 权值为tot 我们称这棵 ...
- 严格次小生成树[BJWC2010] (树链剖分,倍增,最小生成树)
题目链接 Solution 有几点关键,首先,可以证明次小生成树一定是由最小生成树改变一条边而转化来. 所以需要枚举所有非最小生成树的边\((u,v)\).并且找到 \(u\) 到 \(v\) 的边中 ...
随机推荐
- Doctype的作用?严格模式与混合模式,如何触发者这两种模式,区分它们有何意义?
Doctype作用?严格模式与混合模式,如何触发者这两种模式,区分它们有何意义? 1.1 Doctype作用 <!DOCTYPE>声明叫做文件类型定义(DTD),声明的作用为了告诉浏览器该 ...
- 【Android】用Cubism 2制作自己的Live2D——软件的安装与破解!
前言- 上文我们简单的了解了Cubism的情况,但是Cubism 2.X安装好以后如果不进行破解只能使用Free版本,这是我们接受不了的,我们是专业的.是来学习的,怎么能不用Pro版本呢?所以话不多说 ...
- 无限极分类(adjacency list)的三种方式(迭代、递归、引用)
一般的分类树状结构有两种方式: 一种是adjacency list,也就是是id,parent id这中形式. 另一种是nested set,即左右值的形式. 左右值形式查询起来比较高效,无需递归等, ...
- compaTtelrunner 和win7补丁的那些事
win7 KB2952664的补丁,卸载即可,无关大碍.该进程严重影响磁盘性能.
- nginx平滑升级(1.14--1.15)
查看旧版nginx编译参数 [root@localhost yum.repos.d]# nginx -V nginx version: nginx/1.14.2 built by gcc 4.8.5 ...
- android 6.0 Intent 安装apk闪退
需求描述: 利用android系统自带的DownloadManager下载apk文件,并且打开安装界面. 问题描述: 关于DownloadManager的使用网上有很多例子,在此不啰嗦.下载完成之后在 ...
- php 微信模板消息发送
<?php ini_set ( 'date.timezone', 'Asia/Shanghai' ); define ( 'IN_ASK2', TRUE ); $http_type = ((is ...
- 【vue】iView-admin2.0动态菜单路由
vue项目实现动态路由有俩种方式 一.前端在routers中写好--所有--路由表 <前端控制路由>,登录时根据用户的角色权限来动态的显示菜单路由 二.前端通过调用接口请求拿到当前用户-- ...
- Fum uc M-R ko P's R
Milr-Rabin Dodod Avlo se \(n-1\) e \(u\cdot 2^t\). hen goch'n Toizz lme \([1,n-1]\) e \(l\). cak fe ...
- Redis的常见用法
Redis redis是一个key-value存储系统.和Memcached类似,它支持存储的value类型相对更多,包括string(字符串).list(链表).set(集合).zset(sorte ...