题目链接\(Click\) \(Here\)

题意就是要求一个图的严格次小生成树。以前被题面吓到了没敢做,写了一下发现并不难。

既然要考虑次小我们就先考虑最小。可以感性理解到一定有一种次小生成树,可以由最小生成树删一条边再加一条边得到。我们枚举加上去的这一条边,加上去以后原\(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,倍增的更多相关文章

  1. 「LuoguP4180」 【模板】严格次小生成树[BJWC2010](倍增 LCA Kruscal

    题目描述 小C最近学了很多最小生成树的算法,Prim算法.Kurskal算法.消圈算法等等.正当小C洋洋得意之时,小P又来泼小C冷水了.小P说,让小C求出一个无向图的次小生成树,而且这个次小生成树还得 ...

  2. 【洛谷 P4180】【模板】严格次小生成树[BJWC2010](倍增)

    题目链接 题意如题. 这题作为我们KS图论的T4,我直接打了个很暴力的暴力,骗了20分.. 当然,我们KS里的数据范围远不及这题. 这题我debug了整整一个晚上还没debug出来,第二天早上眼前一亮 ...

  3. 【luogu P4180 严格次小生成树[BJWC2010]】 模板

    题目链接:https://www.luogu.org/problemnew/show/P4180 这个题卡树剖.记得开O2. 这个题inf要到1e18. 定理:次小生成树和最小生成树差距只有在一条边上 ...

  4. P4180-[BJWC2010]严格次小生成树【Kruskal,倍增】

    正题 题目链接:https://www.luogu.com.cn/problem/P4180 题目大意 \(n\)个点\(m\)条边的一张无向图,求它的严格次小生成树. \(1\leq n\leq 1 ...

  5. Luogu P4180 【模板】严格次小生成树[BJWC2010]

    P4180 [模板]严格次小生成树[BJWC2010] 题意 题目描述 小\(C\)最近学了很多最小生成树的算法,\(Prim\)算法.\(Kurskal\)算法.消圈算法等等.正当小\(C\)洋洋得 ...

  6. P4180 【模板】严格次小生成树[BJWC2010]

    P4180 [模板]严格次小生成树[BJWC2010] 倍增(LCA)+最小生成树 施工队挖断学校光缆导致断网1天(大雾) 考虑直接枚举不在最小生成树上的边.但是边权可能与最小生成树上的边相等,这样删 ...

  7. 【洛谷】4180:【模板】严格次小生成树[BJWC2010]【链剖】【线段树维护最大、严格次大值】

    P4180 [模板]严格次小生成树[BJWC2010] 题目描述 小C最近学了很多最小生成树的算法,Prim算法.Kurskal算法.消圈算法等等.正当小C洋洋得意之时,小P又来泼小C冷水了.小P说, ...

  8. 【题解】洛谷P4180 [BJWC2010] 严格次小生成树(最小生成树+倍增求LCA)

    洛谷P4180:https://www.luogu.org/problemnew/show/P4180 前言 这可以说是本蒟蒻打过最长的代码了 思路 先求出此图中的最小生成树 权值为tot 我们称这棵 ...

  9. 严格次小生成树[BJWC2010] (树链剖分,倍增,最小生成树)

    题目链接 Solution 有几点关键,首先,可以证明次小生成树一定是由最小生成树改变一条边而转化来. 所以需要枚举所有非最小生成树的边\((u,v)\).并且找到 \(u\) 到 \(v\) 的边中 ...

随机推荐

  1. Android ViewPager+Fragment 在Activity中获取Fragment的控件

    如果ViewPager+Fragment实现Tab切换,在activity中利用adapter.getItem获取到fragment然后再根据fragment.的方法获取控件 //隐藏求租,以下代码用 ...

  2. 使用 Scrapy 爬取股票代码

    个人博客: https://mypython.me 源码地址: https://github.com/geeeeeeeek/scrapy_stock 抓取工具:scrapy scrapy 介绍 Scr ...

  3. Android View的重绘ViewRootImpl的setView方法

    博客首页:http://www.cnblogs.com/kezhuang/p/ 本篇文章来分析一下WindowManager的后续工作,也就是ViewRootImpl的setView函数的工作 /i* ...

  4. Git的安装与配置

    在安装Git之前,首先要下载Git安装包. 下载地址:https://gitforwindows.org/ 下载完后打开安装:如下步骤                       按着以上步骤安装完成 ...

  5. 20年硅谷技术牛人到访DataPipeline谈:技术如何与业务平衡发展

    导读:技术人员的常态是“左手支持业务签单,右手提升系统性能”,却经常陷入技术和业务该如何平衡发展的困惑?今天,且听一位硅谷牛人分享他的平衡之道. 以个人名誉申请31个国内外技术和产品专利,中国最佳CT ...

  6. Diagnostics: File file:/tmp/spark-95cbb984-da28-4784-8b99-eb83ad74437f/__spark_libs__1421840316395076250.zip does not exist

    搭建spark环境,测试在yarn 上运行spark shell的时候出现的错误:Diagnostics: File file:/tmp/spark-95cbb984-da28-4784-8b99-e ...

  7. 码农也来关注下经济问题<美元加息>对我们的影响

    昨天凌晨三点,美联储宣布加息25个基点,这是今年美联储第四次加息,也是2015年12月份以来的第九次加息.基准利率又上调了25个基点,全球市场又要开始惴惴不安了. 要知道上一次美国基准利率上调25个基 ...

  8. 我为什么要花大力气从头研发智表ZCELL(一个仿EXCEL的前端插件)

    为什么呢,一个前端用的,类似EXCEL的操作的JS 插件,从头研发真的有必要吗?可能你会觉得没有必要吧,其实我自己也问过自己好多遍.因为业界有更加强大的spreadjs,也有比较轻型的JEXCEL,自 ...

  9. Doctype知识点总结

    DOCTYPE是document type (文档类型) 的缩写.<!DOCTYPE >声明位于文档的最前面,处于标签之前,它不是html标签.主要作用是告诉浏览器的解析器使用哪种HTML ...

  10. 如何改善SSH连接过慢(效率)

    +++++++++++++++++++++++++++++++++++++++++问题:通过SSH链接远程Linux主机过慢.重点:学习如何通过调整ssh_config配置文件,提高SSH连接效率.时 ...