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

在其上浪一个早上,你的

最小生成树 树链剖分 线段树 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. VueX数据持久化

    解决:Vue刷新时获取不到数据 解决方案:1.本地存储 2.Vuex数据持久化工具插件 本地存储 import Vue from "vue"; import Vuex from & ...

  2. 【AC自动机】背单词

    题意: 0 s v:添加价值为v的字符串s 1 t:查询t中含的s的权值和.(不停位置算多次) 思路: 在线AC自动机. 同学用过一个妙妙子的分块算法. 这里用二进制分组:通常用作把在线数据结构问题转 ...

  3. Linux namespace技术应用实践--调用宿主机命令(tcpdump/ip/ps/top)检查docker容器网络、进程状态

    背景 最近偶然听了几堂极客时间的云原生免费公开课程,首次接触到了Linux namespace技术,并了解到这正是现在风头正劲的容器技术基石,引起了自己探究一二的兴趣,结合课程+网络搜索+实践操作,也 ...

  4. 我用 AntV/S2 买了一套房

    背景 经过一年多的摇号,我在前两天收到了某网红盘的摇中通知.还沉浸在摇中房屋喜悦中的我,很快被售房顾问告知选房的人很多,每位购房者的选房时间都很短,必须 一分钟内 快速选房.并且,排在 400 多号的 ...

  5. 4.怎么理解相互独立事件?真的是没有任何关系的事件吗? 《zobol的考研概率论教程》

    1.从条件概率的定义来看独立事件的定义 2.从古典概率的定义来看独立事件的定义 3.P(A|B)和P(A)的关系是什么? 4.由P(AB)=P(A)P(B)推出"独立" 5.从韦恩 ...

  6. Tomcat部署界面使用burp爆破

    打开界面显示私密连接,正常抓包. 抓包查看Authorization的数据 Basic 后面的数据是经过base64加密后的.格式为admin:123456 勾选对应参数,payload设置为Cust ...

  7. 5.RDD操作综合实例

    一.词频统计 A. 分步骤实现 1.准备文件 (1)下载小说或长篇新闻稿 (2)上传到hdfs上 2.读文件创建RDD 3.分词 4. ·排除大小写lower(),map() ·标点符号re.spli ...

  8. 使用 Cheat Engine 修改 Kingdom Rush 中的金钱、生命、星

    最新博客链接 最近想学习一下 CE,刚好看见游戏库里装了 Kingdom Rush 就拿它来研究吧.这里写的东西,需要一些 Cheat Engine 的基础,可以看看教程. 这里主要是看写的注释,来理 ...

  9. Django【执行查询】(二)

    官方Django3.2 文档:https://docs.djangoproject.com/en/3.2/topics/db/queries/ 本文大部分内容参考官方3.2版本文档撰写,仅供学习使用 ...

  10. 集合—collection、iterator遍历集合

    一.collection接口 1.collection常用方法 点击查看代码 @Test public void test(){ //contains() Collection coll = new ...