#Kruskal重构树,Dijkstra,倍增#洛谷 4768 [NOI2018]归程
分析
首先Dijkstra是必需的(关于SPFA,它死了233)
无向图,所以先求出1号节点到所有点的距离,然后肯定希望起点能驾驶到离一号点最短的汽车可到的地方
但是怎么办,考虑海拔大的边肯定会更想选,那为什么不用Kruskal建出一棵最大生成树
但是怎么求呢,Kruskal重构树横空出世,通过用新点连接原来两点,建起一棵\(2n-1\)个点的树
那有什么用呢,这棵树变成了二叉堆,在本题中还是小根堆,也就是两点LCA代表了重构树路径上最小边
那边再求个最小值不就可以用倍增解决了吗
代码
#include <cstdio>
#include <cctype>
#include <cstring>
#include <algorithm>
#define rr register
using namespace std;
const int N=400011;
struct rec{int x,y,w,c;}T[N]; struct node{int y,w,next;}e[N<<1]; struct Node{int y,next;}E[N];
int ls[N>>1],hs[N],dis[N],h[N],dep[N],n,m,k,K,cnt,nnt,f[N][20],Q,opt,S,fat[N]; pair<int,int>heap[N>>1];
inline signed iut(){
rr int ans=0; rr char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) ans=(ans<<3)+(ans<<1)+c-48,c=getchar();
return ans;
}
inline void add(int x,int y,int w){e[++k]=(node){y,w,ls[x]}; ls[x]=k;}
inline void Add(int x,int y){E[++K]=(Node){y,hs[x]},hs[x]=K;}
inline void print(int ans){
if (ans>9) print(ans/10);
putchar(ans%10+48);
}
inline void Push(pair<int,int>w){
heap[++cnt]=w;
rr int x=cnt;
while (x>1){
if (heap[x>>1]>heap[x])
swap(heap[x>>1],heap[x]),x>>=1;
else return;
}
}
inline void Pop(){
heap[1]=heap[cnt--];
rr int x=1;
while ((x<<1)<=cnt){
rr int y=x<<1;
if (y<cnt&&heap[y+1]<heap[y]) ++y;
if (heap[y]<heap[x]) swap(heap[y],heap[x]),x=y;
else return;
}
}
inline void Dijkstra(){
dis[1]=0,heap[++cnt]=make_pair(0,1);
while (cnt){
rr int x=heap[1].second,t=heap[1].first;
Pop(); if (t!=dis[x]) continue;
for (rr int i=ls[x];i;i=e[i].next)
if (dis[e[i].y]>dis[x]+e[i].w){
dis[e[i].y]=dis[x]+e[i].w;
Push(make_pair(dis[e[i].y],e[i].y));
}
}
}
bool cmp(rec x,rec y){return x.c>y.c;}
inline signed getf(int u){return fat[u]==u?u:fat[u]=getf(fat[u]);}
inline void Kruskal(){
for (rr int i=1;i<n*2;++i) fat[i]=i;
for (rr int i=1,tot=0;i<=m;++i){
rr int fa=getf(T[i].x),fb=getf(T[i].y);
if (fa!=fb){
fat[fa]=fat[fb]=++nnt,h[nnt]=T[i].c;
Add(nnt,fa),Add(nnt,fb);
if (++tot==n-1) return;
}
}
}
inline void dfs(int x,int fa){
dep[x]=dep[fa]+1,f[x][0]=fa;
for (rr int i=1;i<20;++i) f[x][i]=f[f[x][i-1]][i-1];
for (rr int i=hs[x];i;i=E[i].next)
dfs(E[i].y,x),dis[x]=min(dis[x],dis[E[i].y]);
}
inline signed GetF(int x,int H){
for (rr int i=19;~i;--i)
if (dep[x]>=(1<<i)&&h[f[x][i]]>H) x=f[x][i];
return dis[x];
}
signed main(){
for (rr int Test=iut();Test;--Test){
memset(ls,0,sizeof(ls)),memset(f,0,sizeof(f));
memset(dep,0,sizeof(dep)),memset(hs,0,sizeof(hs));
memset(h,0,sizeof(h)),memset(dis,0x3f,sizeof(dis));
n=iut(),m=iut(),k=K=1,nnt=n;
for (rr int i=1;i<=m;++i){
T[i]=(rec){iut(),iut(),iut(),iut()};
add(T[i].x,T[i].y,T[i].w);
add(T[i].y,T[i].x,T[i].w);
}
Dijkstra(),sort(T+1,T+1+m,cmp),Kruskal(),
dfs(nnt,0),Q=iut(),opt=iut(),S=iut();
for (rr int lastans=0;Q;Q--){
rr int G=iut(),H=iut();
if (opt) G=(G+lastans-1)%n+1,H=(H+lastans)%(S+1);
print(lastans=GetF(G,H)),putchar(10);
}
}
return 0;
}
#Kruskal重构树,Dijkstra,倍增#洛谷 4768 [NOI2018]归程的更多相关文章
- NOI Day1T1归程(Kruskal重构树+Dijkstra)
NOI Day1T1归程(Kruskal重构树+Dijkstra) 题目 洛谷题目传送门 题解 其实我不想写......,所以...... 挖个坑......我以后一定会补的 luogu的题解讲的还是 ...
- [洛谷P4768] [NOI2018]归程 (kruskal重构树模板讲解)
洛谷题目链接:[NOI2018]归程 因为题面复制过来有点炸格式,所以要看题目就点一下链接吧\(qwq\) 题意: 在一张无向图上,每一条边都有一个长度和海拔高度,小\(Y\)的家在\(1\)节点,并 ...
- 洛谷P4768 [NOI2018]归程(Kruskal重构树)
题意 直接看题目吧,不好描述 Sol 考虑暴力做法 首先预处理出从$1$到每个节点的最短路, 对于每次询问,暴力的从这个点BFS,从能走到的点里面取$min$ 考虑如何优化,这里要用到Kruskal重 ...
- UVA1265 Tour Belt Kruskal重构树、倍增、树上差分
题目传送门 题意:定义$Tour \, Belt$为某张图上的一个满足以下条件的点集:①点集中至少有$2$个点②任意两点互相连通③图上两个端点都在这个点集中的边的权值的最小值严格大于图上只有一个端点在 ...
- 【BZOJ 3551】[ONTAK2010] Peaks加强版 Kruskal重构树+树上倍增+主席树
这题真刺激...... I.关于Kruskal重构树,我只能开门了,不过补充一下那玩意还是一棵满二叉树.(看一下内容之前请先进门坐一坐) II.原来只是用树上倍增求Lca,但其实树上倍增是一种方法,L ...
- 洛谷P4768 [NOI2018]归程 [可持久化并查集,Dijkstra]
题目传送门 归程 格式难调,题面就不放了. 分析: 之前同步赛的时候反正就一脸懵逼,然后场场暴力大战,现在呢,还是不会$Kruskal$重构树,于是就拿可持久化并查集做. 但是之前做可持久化并查集的时 ...
- 洛谷 P4768 [NOI2018]归程
洛谷 361行代码的由来 数据分治大发好啊- NOI的签到题,可怜我在家打了一下午才搞了80分. 正解应该是kruskal重构树或排序+可持久化并查集. 我就分点来讲暴力80分做法吧(毕竟正解我也没太 ...
- 洛谷P4768 [NOI2018]归程(克鲁斯卡尔重构树+最短路)
传送门 前置技能,克鲁斯卡尔重构树 我们按道路的高度建一个最大生成树,然后建好克鲁斯卡尔重构树 那么我们需要知道一颗子树内到1点距离最近是多少(除此之外到子树内任何一个点都不需要代价) 可以一开始直接 ...
- 洛谷$P4768\ [NOI2018]$归程 $kruscal$重构树
正解:$kruscal$重构树 解题报告: 传送门$QwQ$ 语文不好选手没有人权$TT$连题目都看不懂真的要哭了$kk$ 所以先放个题目大意?就说给定一个$n$个点,$m$条边的图,每条边有长度和海 ...
- 洛谷P4768 [NOI2018]归程(可持久化并查集,最短路)
闲话 一个蒟蒻,在网络同步赛上进行了这样的表演-- T2组合计数不会,T3字符串数据结构不会,于是爆肝T1 一开始以为整个地图都有车,然后写了2h+的树套树,终于发现样例过不去 然后写可持久化并查集D ...
随机推荐
- Rock Pi开发笔记(三):Rock Pi 4B plus(基于瑞星微RK3399)板子硬件资源介绍
前言 上一篇,概览了整个的rock pi大致系列,我们开始定位为RK3399做评估,入手RK3399,对基本的外设进行解说. 板载外设 USB3.0 × 2 USB2.0 × 2 千 ...
- python中动态生成类type的用法
示例:正常创建类 class Person(object): def __init__(self): self.name = name self.age = age p = Person(" ...
- 【Azure 云服务】Cloud Service Worker Role Workerrole突然停机,查看Events发现 Defrag Error (0x8900002D)
问题描述 Cloud Service Worker Role Workerrole突然停机,查看Events,发现是错误源为 Defrag. 错误消息: The volume Windows was ...
- 图数据库实操:用 Nebula Graph 破解成语版 Wordle 谜底
本文首发于 Nebula Graph Community 公众号 春节期间如果有小伙伴玩过 Wordle 这个火爆社交媒体的猜词游戏,可能对成语版本的汉兜有所耳闻.在玩汉兜过程中,我发现用 Nebul ...
- C++之指针变量的定义和使用
从b站上黑马程序员的c++课里学到的C++之指针变量的定义和使用 指针变量的定义和使用 简单理解指针就是地址. 内存编号是从0开始记录的,一般用16进制数字表示 1 #include <iost ...
- Glide源码解析三(注册组件)
转载请标明出处,维权必究: https://www.cnblogs.com/tangZH/p/12900387.html Glide源码解析一,初始化 Glide源码解析二-into方法 Glide源 ...
- Java 数组对象 小测试
1 package com.bytezero.bank; 2 /** 3 * 4 * @Description 5 * @author Bytezero·zhenglei! Email:4204982 ...
- B. Ela's Fitness and the Luxury Number
思路: \[能想到平方是比较特殊的,因为x*x一定是x的倍数也就是说\sqrt[2]{x*x} = {x} \] \[所以需要考虑平法之间的数手模一下样例可以发现 [x^2 ,(x+1)^2)之间是x ...
- 【主流技术】日常工作中关于 JSON 转换的经验大全(Java)
目录 前言 一.JSON 回顾 1.1结构形式 二.其它类型 -> JSON相关 2.1 JavaBean 转 JsonObject 2.2 JavaBean 转 Json 字符串 2.3 Li ...
- nginx四层和七层负载的配置
四层负载和七层负载是两种不同类型的负载均衡策略,它们分别在网络的不同层次上工作.在Nginx中,这两种负载均衡策略可以通过配置nginx.conf文件来实现. 四层负载(L4 Load Balanci ...