BZOJ1977/LuoguP4180【模板】严格次小生成树[BJWC2010] (次小生成树)
这道题本身思维难度不大,但综合性强,细节多
在其上浪一个早上,你的
最小生成树 树链剖分 线段树 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] (次小生成树)的更多相关文章
- 「LuoguP4180」 【模板】严格次小生成树[BJWC2010](倍增 LCA Kruscal
题目描述 小C最近学了很多最小生成树的算法,Prim算法.Kurskal算法.消圈算法等等.正当小C洋洋得意之时,小P又来泼小C冷水了.小P说,让小C求出一个无向图的次小生成树,而且这个次小生成树还得 ...
- P4180 【模板】严格次小生成树[BJWC2010]
P4180 [模板]严格次小生成树[BJWC2010] 倍增(LCA)+最小生成树 施工队挖断学校光缆导致断网1天(大雾) 考虑直接枚举不在最小生成树上的边.但是边权可能与最小生成树上的边相等,这样删 ...
- 【洛谷】4180:【模板】严格次小生成树[BJWC2010]【链剖】【线段树维护最大、严格次大值】
P4180 [模板]严格次小生成树[BJWC2010] 题目描述 小C最近学了很多最小生成树的算法,Prim算法.Kurskal算法.消圈算法等等.正当小C洋洋得意之时,小P又来泼小C冷水了.小P说, ...
- Luogu P4180 【模板】严格次小生成树[BJWC2010]
P4180 [模板]严格次小生成树[BJWC2010] 题意 题目描述 小\(C\)最近学了很多最小生成树的算法,\(Prim\)算法.\(Kurskal\)算法.消圈算法等等.正当小\(C\)洋洋得 ...
- 洛谷 P4180 【模板】严格次小生成树[BJWC2010]【次小生成树】
严格次小生成树模板 算法流程: 先用克鲁斯卡尔求最小生成树,然后给这个最小生成树树剖一下,维护边权转点权,维护最大值和严格次大值. 然后枚举没有被选入最小生成树的边,在最小生成树上查一下这条边的两端点 ...
- 【【模板】严格次小生成树[BJWC2010]】
树上的路径怎么能没有树剖 显然,次小生成树和最小生成树只在一条边上有差距,于是我们就可以枚举这一条边,将所有边加入最小生成树,之后再来从这些并不是那么小的生成树中找到那个最小的 我们往最小生成树里加入 ...
- 【luogu P4180 严格次小生成树[BJWC2010]】 模板
题目链接:https://www.luogu.org/problemnew/show/P4180 这个题卡树剖.记得开O2. 这个题inf要到1e18. 定理:次小生成树和最小生成树差距只有在一条边上 ...
- 【洛谷 P4180】【模板】严格次小生成树[BJWC2010](倍增)
题目链接 题意如题. 这题作为我们KS图论的T4,我直接打了个很暴力的暴力,骗了20分.. 当然,我们KS里的数据范围远不及这题. 这题我debug了整整一个晚上还没debug出来,第二天早上眼前一亮 ...
- 洛谷P4180 【模板】严格次小生成树[BJWC2010] 题解
虽然中途写的时候有点波折,但是最后一发A,还是有点爽. 这虽然是个模板题,但还是涉及到许多知识的= = 首先我们求出一个最小生成树,并且求出其边权和\(ans\).那么现在考虑加入其它的边,每次加入在 ...
随机推荐
- 20212115朱时鸿实验一《python程序设计》实验报告
------------恢复内容开始------------ #学号20212115 <python程序设计>实验一报告 课程: <python程序设计> 班级:2121 姓名 ...
- 第一次的ssm整合
数据库表 导入依赖 <dependencies> <dependency> <groupId>javax.servlet</groupId> <a ...
- 从零开始实现lmax-Disruptor队列(一)RingBuffer与单生产者、单消费者工作原理解析
1.lmax-Disruptor队列介绍 disruptor是英国著名的金融交易所lmax旗下技术团队开发的一款java实现的高性能内存队列框架 其发明disruptor的主要目的是为了改进传统的内存 ...
- 「Java分享客栈」Nacos配置中心称王称霸,我Apollo一生也不弱于人!
前言 Apollo又称阿波罗配置中心,在前两年还是挺火的,但阿里SpringCloud套件席卷国内之后,nacos就成为了最被亲睐的分布式配置中心,nacos是配置中心和注册中心二合一的产品,单纯功能 ...
- 2020.10.17【普及组】模拟赛C组 总结
总结 这次比赛 120 分,老师说上 200 是不容易的,但我觉得这不是我真的水平 改题情况 T1 题目大意:有 N 个小朋友,每个小朋友有 \(B_i\) 个朋友,问从中随机选 3 人使得 3 人关 ...
- vs code nginx php xdebug配置
终于把VSCODE XDEBUG配置搞定了 分享一下 1. VSCODE 安装插件 PHP Debug( Debug supprot for PHP with XDebug); 2. VSCODE ...
- 解决Windows微软账户无法登录
更新记录 2022年4月16日:本文迁移自Panda666原博客,原发布时间:2021年8月25日. 将DNS的服务器地址修改为4.2.2.1或者4.2.2.2就可以解决无法登录microsoft账户 ...
- cve_2019_0708_bluekeep漏洞
一.环境说明 kali linux windows 7 sp1 二.cve_2019_0708_bluekeep漏洞利用 msf5 auxiliary(dos/windows/rdp/ms12_020 ...
- 拉取服务器上的项目,svn认证失败
解决方案: 在服务器上找到对应的项目路径,并修改authz: 我的是因为[group]组下(下图中34行),我写的是[demo:/],改为[/]就可以了.
- Lua5.4源码剖析:二. 详解String数据结构及操作算法
概述 lua字符串通过操作算法和内存管理,有以下优点: 节省内存. 字符串比较效率高.(比较哈希值) 问题: 相同的字符串共享同一份内存么? 相同的长字符串一定不共享同一份内存么? lua字符串如何管 ...