这道题本身思维难度不大,但综合性强,细节多

在其上浪一个早上,你的

最小生成树 树链剖分 线段树 DEBUG能力...

都大幅提升

细节与思路都在代码里面了。

欢迎hack.

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define R(a,b,c) for(register int a = (b); a <= (c); ++a)
#define nR(a,b,c) for(register int a = (b); a >= (c); --a)
#define Max(a,b) ((a) > (b) ? (a) : (b))
#define Min(a,b) ((a) < (b) ? (a) : (b))
#define ll long long
#define Fill(a,b) memset(a, b, sizeof(a)) //#define ON_DUBUG #ifdef ON_DUBUG #define D_e_Line printf("\n\n-------------------\n\n") #else #define D_e_Line ; #endif struct ios{
template<typename ATP>ios& operator >> (ATP &x){
x = 0; int f = 1; char c;
for(c = getchar(); c < '0' || c > '9'; c=getchar()) if(c == '-') f = -1;
while(c >= '0' && c <='9') x = x * 10 + (c ^ '0'), c = getchar();
x *= f;
return *this;
}
}io; using namespace std; //#define TEST_INPUT
#ifdef TEST_INPUT
int main(){
while(1){
ll x;
io >> x;
cout << x << endl;
}
}
#endif const int N = 100007;
const int M = 300007; int n, m; struct Node{
int x,y,w,tag;
bool operator < (const Node &b)const{
return w < b.w;
}
}a[M];
struct Edge{
int nxt,pre;
long long w;
}e[M<<1];
int head[N],cntEdge;
inline void add(int u,int v,long long w){
e[++cntEdge] = (Edge){head[u], v, w}, head[u] = cntEdge;
} long long MST;
int f[N];
inline int Find(int x){
return x == f[x] ? x : f[x] = Find(f[x]);
}
inline void Kruskal(){
R(i,1,n) f[i] = i;//Always remember, Fool orphan! Get your father at the first time!
sort(a + 1, a + m + 1);
int tot = 1;
R(i,1,m){
int p = Find(a[i].x), q =Find(a[i].y);
if(p != q){
f[p] = q;
MST += a[i].w;
a[i].tag = true;
if(++tot >= n)
return;
}
} } int wSon[N];
int fa[N],son[N],siz[N],dep[N];
inline void DFS_First(int u,int father){
dep[u] = dep[father] + 1, siz[u] = 1, fa [u] = father;
for(register int i = head[u]; i; i = e[i].nxt){
int v = e[i].pre;
if(v == father) continue;
DFS_First(v, u);
siz[u] += siz[v];
if(!son[u] || siz[v] > siz[son[u]]){
son[u] = v;
//Treat value(edge) as value(node)
wSon[u] = e[i].w;
}
}
}
int top[N],rnk[N],dfn[N],dfnIndex;
inline void DFS_Second(int u,int ancester,int w){
top[u] = ancester, dfn[u] = ++dfnIndex, rnk[dfnIndex] = w;
if(!son[u]) return;
DFS_Second(son[u], ancester, wSon[u]);//e[i].w or wSon[u] ? // The answer is wSon[u] because it's the weight of this node
for(register int i = head[u]; i; i = e[i].nxt){
int v = e[i].pre;
if(v != fa[u] && v != son[u])
DFS_Second(v, v, e[i].w);//e[i].w or wSon[u] ? // The answer is e[i].w because it's the cost to the next node.
}
} #define lson rt << 1, l, mid
#define rson rt << 1 | 1, mid + 1, r
struct SegmentTree{
int mx,sc;
}t[M<<2];
inline void Pushup(int rt){
t[rt].mx = Max(t[rt<<1].mx, t[rt<<1|1].mx);
t[rt].sc = Max(t[rt].mx != t[rt<<1].mx ? t[rt<<1].mx : t[rt<<1].sc, t[rt].mx != t[rt<<1|1].mx ? t[rt<<1|1].mx : t[rt<<1|1].sc);
}
inline void Build(int rt,int l,int r){
if(l == r){
t[rt].mx = rnk[l];
t[rt].sc = -1;
//Pushup(rt);//Do there really need pushup? // No! You do not have to pull a tree you just put into the groud.
return;
}
int mid = l + r >> 1;
Build(lson), Build(rson);
Pushup(rt);
}
SegmentTree Query(int rt,int l,int r,int L,int R){
if(L <= l && r <= R) return t[rt]; SegmentTree tmp_1, tmp_2, res;
tmp_1.mx = tmp_1.sc = tmp_2.mx = tmp_2.sc;//Need initial? And why?
/*
There is a strange problem
if I don't initial, the program will give a wrong answer.
But if I write:
tmp_1.mx = tmp_1.sc = tmp_2.mx = tmp_2.sc
It'll be right.
Pay attention, I do not write:
tmp_1.mx = tmp_1.sc = tmp_2.mx = tmp_2.sc = 0 So what happend to this initial sentence?
I believe you can find out by yourself.
*/ int mid = l + r >> 1;
//D_e_Line;
if(L <= mid) tmp_1 = Query(lson, L, R);
if(mid < R) tmp_2 = Query(rson, L, R); res.mx = Max(tmp_1.mx, tmp_2.mx);
res.sc = Max(res.mx != tmp_1.mx ? tmp_1.mx : tmp_1.sc, res.mx != tmp_2.mx ? tmp_2.mx : tmp_2.sc); return res;
} inline long long QueryPath(int u,int v,long long w){
long long sum = 0;
while(top[u] != top[v]){
if(dep[top[u]] < dep[top[v]]) u^=v^=u^=v;
SegmentTree tmp = Query(1, 1, n, dfn[top[u]], dfn[u]);
sum = Max(sum, tmp.mx != w ? tmp.mx : tmp.sc);
u = fa[top[u]];
}
if(u == v) return sum;//Is this so important? Is it the criminal of the endless of my program?//Well, for the second question, it may not. //And if I ignore it, it doesn't matter, but as it can make my program runs faster, why not?
if(dep[u] < dep[v]) u^=v^=u^=v;
SegmentTree tmp = Query(1, 1, n, dfn[v]+1, dfn[u]);//I'm not sure when I need use 'dfn[v]+1'
sum = Max(sum, tmp.mx != w ? tmp.mx : tmp.sc);
return sum;
} int main(){
io >> n >> m;
R(i,1,m){
int u,v,w;
io >> u >> v >> w;
a[i] = (Node){u, v, w, 0};
} Kruskal(); R(i,1,m){//Here ought to be m, not n! It's going through all the edges
if(a[i].tag == true){
add(a[i].x, a[i].y, a[i].w);
add(a[i].y, a[i].x, a[i].w);
}
} DFS_First(1, 0);
DFS_Second(1, 0, 0); Build(1, 1, n); int sum = 2147483647;
R(i,1,m){
if(a[i].tag == false){
sum = Min(sum, a[i].w - QueryPath(a[i].x, a[i].y, a[i].w));
}
} printf("%lld\n", MST + sum); return 0; }

BZOJ1977/LuoguP4180【模板】严格次小生成树[BJWC2010] (次小生成树)的更多相关文章

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

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

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

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

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

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

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

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

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

    严格次小生成树模板 算法流程: 先用克鲁斯卡尔求最小生成树,然后给这个最小生成树树剖一下,维护边权转点权,维护最大值和严格次大值. 然后枚举没有被选入最小生成树的边,在最小生成树上查一下这条边的两端点 ...

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

    树上的路径怎么能没有树剖 显然,次小生成树和最小生成树只在一条边上有差距,于是我们就可以枚举这一条边,将所有边加入最小生成树,之后再来从这些并不是那么小的生成树中找到那个最小的 我们往最小生成树里加入 ...

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

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

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

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

  9. 洛谷P4180 【模板】严格次小生成树[BJWC2010] 题解

    虽然中途写的时候有点波折,但是最后一发A,还是有点爽. 这虽然是个模板题,但还是涉及到许多知识的= = 首先我们求出一个最小生成树,并且求出其边权和\(ans\).那么现在考虑加入其它的边,每次加入在 ...

随机推荐

  1. 实验一:在FW上配置静态路由实现互通

    实验:在FW上配置静态路由实现互通 网络拓扑图 一.配置步骤 1.配置IP地址 R1: FW: ISP:       2.配置路由 ①在R2上面配置静态路由 ②在ISP上面配置静态路由 3.在FW上配 ...

  2. Docker容器固定ip

    Docker容器固定IP 必须停止docker服务才能创建网桥 查看docker服务状态 停止docker服务 启动docker服务 [root@docker Tools]# systemctl st ...

  3. 【转载】浅谈大规模k8s集群关于events的那些坑

    原文链接:一流铲屎官二流程序员[浅谈大规模k8s集群关于events的那些坑] 背景 随着k8s集群规模的增加,集群内的object数量也与日俱增,那么events的数量也会伴随其大量增加,那么当用户 ...

  4. 编程技巧│浏览器 Notification 桌面推送通知

    目录 一.什么是 Notification 二.弹窗授权 三.弹窗使用 四.浏览器支持检测 五.授权回调 六.3秒后关闭弹窗 一.什么是 Notification Notification 是浏览器最 ...

  5. 使用http://start.spring.io/构建maven微服务项目的几个坑及eclipse构建spring boot微服务项目

    一,使用http://start.spring.io/构建maven微服务项目 本来嘛,直接构建的项目导入时没有任何问题的导入就可以运行,可是最近构建好项目,然后导入,种种报错 1.导入之后POM报错 ...

  6. 下载安装myslq-----win

    在百度上搜索MySQL官网,进入下载页面-->选择社区版(Community)-->选择MySQL Community Server后,点击DOWNLOAD按钮-->Generall ...

  7. VisionPro · C# · 图像保存

    根据客户要求,每次视觉取像运行完毕后,按需保存OK或NG图像,图像分两种: 1.带视觉工具运行结果图像: 2.相机取像原图,.bmp格式. 保存图像代码如下: using System; using ...

  8. 一个bug肝一周...忍不住提了issue

    导航 Socket.IO是什么 Socket.IO的应用场景 为什么选socket.io-client-java 实战案例 参考 本文首发于智客工坊-<socket.io客户端向webserve ...

  9. Python+opencv打开修图的正确方式get

    先逼逼两句: 图像是 Web 应用中除文字外最普遍的媒体格式. 流行的 Web 静态图片有 JPEG.PNG.ICO.BMP 等.动态图片主要是 GIF 格式.为了节省图片传输流量,大型互联网公司还会 ...

  10. IntelliJ IDEA 项目文件旁边都有0%classes,0% lines covered

    IntelliJ IDEA 项目文件旁边都有0%classes,0% lines covered,解决方法:http://yayihouse.com/yayishuwu/chapter/2247