做一次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. RAW模板开发--入口文件官方规范

    每个人都有自己的习惯,为了RAW模板能进一步推广,使RAW模板的开发也更有条理,所以写了这个文章. 规范1格式: <?php /*RAW标记声明-start*/ /*RAW标记声明-over*/ ...

  2. 关于document.selection和TextRange对象的介绍

    document.selection只有IE支持 window.getSelection()也只有FireFox和Safari支持,都不是标准语法. selection 对象代表了当前激活选中区,即高 ...

  3. 【Untiy3D 游戏开发之一】Unity3D For Window/Mac最新4.2.0版本破解教程

    转载请标明:转载自[小枫栏目],博文链接:http://blog.csdn.net/rexuefengye/article/details/11646885 一.Unity3D For Mac 1.首 ...

  4. perl5 第八章 子程序

    第八章 子程序 by flamephoenix 一.定义二.调用  1.用&调用  2.先定义后调用  3.前向引用  4.用do调用三.返回值四.局部变量五.子程序参数传递  1.形式  2 ...

  5. libcurl的使用问题“Expect100-continue”

    最近在做团购酒店APP分享到qzone功能,使用libcurl访问qzone的分享cgi接口,酒店分享信息以POST方式传输,在测试的时候发现分享接口平均有2s的延迟,这延迟也太大了吧,于是乎问了空间 ...

  6. Android4.3模拟器界面中右侧菜单按钮无法使用问题解决办法

    开发环境:笔记本电脑Windows2008+MyEclipse 10+Android4.3 问题描述:运行或者调试Android项目时,发现模拟器中右侧Menu按钮无法点击,截图如下: 查看在Andr ...

  7. 你应当知道的Java牛人

    Java领域有非常多著名的人物,他们为Java社区编写框架.产品.工具或撰写书籍改变了Java编程的方式. 本文是<最受欢迎的8位Java牛人>的2.0版本号. PS:排名不分先后.本文的 ...

  8. 《TCP/IP详细说明》读书笔记(17章)-TCP传输控制协定

    1.TCP的服务 在一个TCP连接中.仅有双方进行彼此通信. TCP通过下列方式来提供可靠性: 1)应用数据被切割成TCP觉得最适合发送的数据块. 这和UDP全然不同,应用程序产生的数据报长度保持不变 ...

  9. 1.自己写一个计算器demo

    知识点: 1.System.Math.Pow() 实现乘方 2.实现计算器的运算优先级,依次调用的流程 问题: 还未实现“()”功能 解决方案 UI:

  10. 面向对象之静态方法(static)和实例化方法的区别

    这是一个经常被时时提出来的问题,很多时候我们以为理解了.懂了,但深究一下,我们却发现并不懂. 方法是我们每天都在写得,很多程序员大多都使用实例化方法,而很少使用静态方法,问原因也说不出来所以然,或者简 ...