做一次MST, 枚举不在最小生成树上的每一条边(u,v), 然后加上这条边, 删掉(u,v)上的最大边(或严格次大边), 更新答案.

树链剖分然后ST维护最大值和严格次大值..倍增也是可以的...

------------------------------------------------------------------------------

#include<bits/stdc++.h>
 
using namespace std;
 
#define b(i) (1 << (i))
typedef long long ll;
 
const int maxn = 100009;
const int maxm = 300009;
 
inline int read() {
int ret = 0;
char c = getchar();
for(; !isdigit(c); c = getchar());
for(; isdigit(c); c = getchar())
   ret = ret * 10 + c - '0';
return ret;
}
 
ll tot = 0;
 
struct edge {
int to, w;
edge* next;
} EDGES[maxn << 1], *pt = EDGES, *head[maxn];
 
inline void add(int u, int v, int w) {
pt->to = v; pt->w = w; pt->next = head[u]; head[u] = pt++;
}
inline void addedge(int u, int v, int w) {
tot += w;
add(u, v, w); add(v, u, w);
}
 
int w[maxn], _id[maxn], N, M;
 
struct data {
int mx, _mx;
data(int _ = -1, int __ = -1):mx(_), _mx(__) {}
};
 
data make(int _, int __) {
return data(_, __);
}
 
data update(data a, data b) {
if(a.mx < b.mx)
   return data(b.mx, max(a.mx, b._mx));
else if(a.mx > b.mx)
   return data(a.mx, max(b.mx, a._mx));
else 
   return data(a.mx, max(a._mx, b._mx));
}
 
struct ST {
static const int maxlog = 20;
data mx[maxn][maxlog];
void init() {
for(int i = 0; i < N; i++) {
mx[i][0].mx = w[_id[i]];
mx[i][0]._mx = -1;
}
for(int i = 1; b(i) <= N; i++)
   for(int j = 0; j + b(i) <= N; j++)
    mx[j][i] = update(mx[j][i - 1], mx[j + b(i - 1)][i - 1]);
}
data query(int x, int y) {
int n = 0;
while(b(n) <= y - x + 1) n++; n--;
return update(mx[x][n], mx[y - b(n) + 1][n]);
}
} st;
 
struct SLPF {
static const int INF = 1000000000;
int top[maxn], size[maxn], son[maxn], dep[maxn], fa[maxn], id[maxn];
int TOP, n;
void dfs(int x) {
size[x] = 1;
son[x] = -1;
for(edge* e = head[x]; e; e = e->next) if(fa[x] != e->to) {
fa[e->to] = x;
dep[e->to] = dep[x] + 1;
w[e->to] = e->w;
dfs(e->to);
size[x] += size[e->to];
if(!~son[x] || size[son[x]] < size[e->to]) son[x] = e->to;
}
}
void DFS(int x) {
top[x] = TOP;
_id[id[x] = n++] = x;
if(~son[x]) DFS(son[x]);
for(edge* e = head[x]; e; e = e->next)
   if(e->to != son[x] && e->to != fa[x]) DFS(TOP = e->to);
}
void init() {
dep[0] = 0; fa[0] = -1;
dfs(0); DFS(n = 0);
}
data query(int x, int y) {
data ret;
for(; top[x] != top[y]; x = fa[top[x]]) {
if(dep[top[x]] < dep[top[y]]) swap(x, y);
ret = update(ret, st.query(id[top[x]], id[x]));
}
if(x == y) return ret;
if(dep[x] < dep[y]) swap(x, y);
return update(ret, st.query(id[y] + 1, id[x]));
}
} slpf;
 
struct EDGE {
int u, v, w;
bool t;
inline void Read() {
u = read() - 1;
v = read() - 1;
w = read();
t = false;
}
bool operator < (const EDGE &e) const {
return w < e.w;
}
} E[maxm];
 
struct DSU {
int p[maxn];
void init() {
for(int i = 0; i < N; i++) p[i] = i;
}
int find(int x) {
return x == p[x] ? x : p[x] = find(p[x]);
}
inline bool unite(int x, int y) {
x = find(x); y = find(y);
p[x] = y;
return x != y;
}
} dsu;
 
void MST() {
sort(E, E + M);
dsu.init();
for(int i = 0; i < M; i++) if(dsu.unite(E[i].u, E[i].v)) {
addedge(E[i].u, E[i].v, E[i].w);
E[i].t = true;
}
}
 
void init() {
scanf("%d%d", &N, &M);
for(int i = 0; i < M; i++) E[i].Read();
}
 
void work() {
slpf.init(); st.init();
ll ans = ll(1e17);
for(int i = 0; i < M; i++) if(!E[i].t) {
data h = slpf.query(E[i].u, E[i].v);
if(E[i].w == h.mx) {
if(~h._mx) ans = min(ans, tot - h._mx + E[i].w);
} else
   ans = min(ans, tot - h.mx + E[i].w);
}
printf("%lld\n", ans);
}
 
int main() {
init();
MST();
work();
return 0;
}

------------------------------------------------------------------------------

1977: [BeiJing2010组队]次小生成树 Tree

Time Limit: 10 Sec  Memory Limit: 512 MB
Submit: 2422  Solved: 578
[Submit][Status][Discuss]

Description

小 C 最近学了很多最小生成树的算法,Prim 算法、Kurskal 算法、消圈算法等等。 正当小 C 洋洋得意之时,小 P 又来泼小 C 冷水了。小 P 说,让小 C 求出一个无向图的次小生成树,而且这个次小生成树还得是严格次小的,也就是说: 如果最小生成树选择的边集是 EM,严格次小生成树选择的边集是 ES,那么需要满足:(value(e) 表示边 e的权值)  这下小 C 蒙了,他找到了你,希望你帮他解决这个问题。

Input

第一行包含两个整数N 和M,表示无向图的点数与边数。 接下来 M行,每行 3个数x y z 表示,点 x 和点y之间有一条边,边的权值为z。

Output

包含一行,仅一个数,表示严格次小生成树的边权和。(数据保证必定存在严格次小生成树)

Sample Input

5 6
1 2 1
1 3 2
2 4 3
3 5 4
3 4 3
4 5 6

Sample Output

11

HINT

数据中无向图无自环; 50% 的数据N≤2 000 M≤3 000; 80% 的数据N≤50 000 M≤100 000; 100% 的数据N≤100 000 M≤300 000 ,边权值非负且不超过 10^9 。

Source

BZOJ 1977: [BeiJing2010组队]次小生成树 Tree( MST + 树链剖分 + RMQ )的更多相关文章

  1. BZOJ 1977[BeiJing2010组队]次小生成树 Tree - 生成树

    描述: 就是求一个次小生成树的边权和 传送门 题解 我们先构造一个最小生成树, 把树上的边记录下来. 然后再枚举每条非树边(u, v, val),在树上找出u 到v 路径上的最小边$g_0$ 和 严格 ...

  2. 【刷题】BZOJ 1977 [BeiJing2010组队]次小生成树 Tree

    Description 小 C 最近学了很多最小生成树的算法,Prim 算法.Kurskal 算法.消圈算法等等. 正当小 C 洋洋得意之时,小 P 又来泼小 C 冷水了.小 P 说,让小 C 求出一 ...

  3. bzoj 1977 [BeiJing2010组队]次小生成树 Tree

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1977 kruscal别忘了先按边权sort.自己觉得那部分处理得还挺好的.(联想到之前某题的 ...

  4. BZOJ 1977: [BeiJing2010组队]次小生成树 Tree 倍增 最小生成树

    好吧我太菜了又调了一晚上...QAQ 先跑出最小生成树,标记树边,再用树上倍增的思路,预处理出: f[u][i] :距离u为2^i的祖先 h[u][i][0/1] :距u点在2^i范围内的最长边和次长 ...

  5. 1977: [BeiJing2010组队]次小生成树 Tree

    1977: [BeiJing2010组队]次小生成树 Tree https://lydsy.com/JudgeOnline/problem.php?id=1977 题意: 求严格次小生成树,即边权和不 ...

  6. [BeiJing2010组队]次小生成树 Tree

    1977: [BeiJing2010组队]次小生成树 Tree Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 5168  Solved: 1668[S ...

  7. 【BZOJ1977】[BeiJing2010组队]次小生成树 Tree 最小生成树+倍增

    [BZOJ1977][BeiJing2010组队]次小生成树 Tree Description 小 C 最近学了很多最小生成树的算法,Prim 算法.Kurskal 算法.消圈算法等等. 正当小 C ...

  8. 洛谷P4180 [Beijing2010组队]次小生成树Tree(最小生成树,LCT,主席树,倍增LCA,倍增,树链剖分)

    洛谷题目传送门 %%%TPLY巨佬和ysner巨佬%%% 他们的题解 思路分析 具体思路都在各位巨佬的题解中.这题做法挺多的,我就不对每个都详细讲了,泛泛而谈吧. 大多数算法都要用kruskal把最小 ...

  9. 【次小生成树】bzoj1977 [BeiJing2010组队]次小生成树 Tree

    Description 小 C 最近学了很多最小生成树的算法,Prim 算法.Kurskal 算法.消圈算法等等. 正当小 C 洋洋得意之时,小 P 又来泼小 C 冷水了.小 P 说,让小 C 求出一 ...

随机推荐

  1. C++编程规范之23:头文件应该自给自足

    摘要: 各司其责:应该确保所编写的每个头文件都能够独自进行编译,为此需要包含其内容所依赖的所有头文件. 如果一个文件包含某个头文件时,还要包含另一个头文件才能工作,就会增加交流障碍,给头文件的用户增添 ...

  2. (Problem 62)Cubic permutations(待续)

    The cube, 41063625 (3453), can be permuted to produce two other cubes: 56623104 (3843) and 66430125 ...

  3. Qt中Ui名字空间以及setupUi函数的原理和实现 <转>

    用最新的QtCreator选择GUI的应用会产生含有如下文件的工程 下面就简单分析下各部分的功能. .pro文件是供qmake使用的文件,不是本文的重点[不过其实也很简单的],在此不多赘述. 所以呢, ...

  4. 修改LVDS支持1024*600分辨率

    一.在boot中增加LVDS设置分辨率1024*600选项 1.修改文件TQIMX6_android-4.2.2\bootable\bootloader\uboot-imx\common\cmd_me ...

  5. shouldOverrideUrlLoading相关说明

    给WebView加一个事件监听对象(WebViewClient)并重写其中的一些方法:shouldOverrideUrlLoading:对网页中超链接按钮的响应.当按下某个连接时WebViewClie ...

  6. [置顶] MongoDB 分布式操作——分片操作

    MongoDB 分布式操作——分片操作 描述: 像其它分布式数据库一样,MongoDB同样支持分布式操作,且MongoDB将分布式已经集成到数据库中,其分布式体系如下图所示: 所谓的片,其实就是一个单 ...

  7. < high performance web sites > 阅读小记

    high performance web sites 1,减少HTTP请求数 (1)图片加载使用image maps 或者 CSS Sprite (2)使用非http协议,如(ftp:, file: ...

  8. poj2492 A Bug's Life【基础种类并查集】

    转载请注明出处,谢谢:http://www.cnblogs.com/KirisameMarisa/p/4298148.html   ---by 墨染之樱花 题目链接:http://poj.org/pr ...

  9. #, about:blank,javascript:路径比较

    试了一下在<a>,<img>,<iframe>中用#,about:blank和javascript: 代码如下: <!Doctype html> < ...

  10. 5种方法去掉HTML中Inline-Block元素之间的空白

    5种方法去掉HTML中Inline-Block元素之间的空白 记得年轻时我在IE6上开发,绝望的希望IE6能支持display: inline-block功能.当需要在”inline”元素上控制mar ...