做一次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. 解决IDAPython: importing "site" failed.的问题

    当我打开IDA6.8时候,里面报Warning, IDAPython: importing "site" failed. WTF!? 我点了OK后,进去发现IDA底部的python ...

  2. poj 1410 计算几何

    /** 注意: 千万得小心..就因为一个分号,调了一个晚上... **/ #include <iostream> #include <algorithm> using name ...

  3. Linux 下的 fork()【转载】

    [原文地址]http://blog.csdn.net/hikaliv/article/details/4276758 [cpp] view plaincopy   for( i = 0; i < ...

  4. grunt切换下载源

    nrm 是一个 NPM 源管理器,允许你快速地在NPM 源间切换: 安装:npm install -g nrm 列出可选源:nrm ls 切换:nrm use taobao 测试所有源连接时间:nrm ...

  5. ftp一些东东

    ftp如果绑定域名 登录时登录名应该写成 域名|用户名

  6. UC/0S2之中断

    中断是计算机系统处理异步事件的重要机制.当异步事件发生时,事件通常是通过硬件向cpu发出中断请求的.在一般情况下,cpu响应这个请求后会立即运行中断服务程序来处理该事件: 为了处理任务延时.任务调度等 ...

  7. js 效果样式大全

    设置 滑动图片背景模糊度 <style type='text/css'>/*透明20%*/.opacity-20 {filter:alpha(opacity=20); /*支持IE浏览器的 ...

  8. 安卓入门学习之Hello,world!

    第二章 Hello,world! 本文同时发表至简书,不为什么,用他的MarkDown在线编辑爽得要哭. 注意:本章节所使用的开发工具为Eclipse 以Android编程权威指南作为学习书物 第一节 ...

  9. Javabean的理解

    1.Javabean是指满足指定规则的Java类.满足的规则由Sun公司提出,如x,setX,getX等规范,public无参构造函数等 2.Javabean其实也是一种规范.

  10. BZOJ 1355: [Baltic2009]Radio Transmission( kmp )

    自己YY一下可以发现answer =  n - fail[ n ] ------------------------------------------------------------------ ...