数据结构(左偏树,可并堆):BNUOJ 3943 Safe Travel
Safe Travel
64-bit integer IO format: %lld Java class name: Main
Each of the cows, of course, wishes not to be harassed and thus chooses an at least slightly different route from pasture_1 (the barn) to pasture_i.
Compute the best time to traverse each of these new not-quite-quickest routes that enable each cow_i that avoid gremlin_i who is located on the final cowpath of the quickest route from pasture_1 to pasture_i.
As usual, the M (2 <= M <= 200,000) cowpaths conveniently numbered 1..M are bidirectional and enable travel to all N (3 <= N <= 100,000) pastures conveniently numbered 1..N. Cowpath i connects pastures a_i (1 <= a_i <= N) and b_i (1 <= b_i <= N) and requires t_i (1 <= t_i <= 1,000) time to traverse. No two cowpaths connect the same two pastures, and no path connects a pasture to itself (a_i != b_i).
Best of all, the shortest path regularly taken by cow_i from pasture_1 to pasture_i is unique in all the test data supplied to your program.
By way of example, consider these pastures, cowpaths, and [times]:
1----[2]----2---+
| | |
[2] [1] [3]
| | |
+-----3---[4]---4
TRAVEL BEST ROUTE BEST TIME LAST PATH
p_1 to p_2 1->2 2 1->2
p_1 to p_3 1->3 2 1->3
p_1 to p_4 1->2->4 5 2->4
When gremlins are present:
TRAVEL BEST ROUTE BEST TIME AVOID
p_1 to p_2 1->3->2 3 1->2
p_1 to p_3 1->2->3 3 1->3
p_1 to p_4 1->3->4 6 2->4
Input
* Lines 2..M+1: Three space-separated integers: a_i, b_i, and t_i
Output
Sample Input
4 5
1 2 2
1 3 2
3 4 4
3 2 1
2 4 3
Sample Output
3
3
6
这道题是世界上第一道树链剖分的题目,我用左偏树AC了。
考虑先建一棵最短路树,一个点去掉树边后,它到根节点的距离就由它的子节点和它自己由非树边连到它这棵子树外的节点来更新,可以维护可并堆。
#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>
using namespace std;
const int maxn=;
const int maxm=;
int cnt,fir[maxn],to[maxm],nxt[maxm],val[maxm];
void addedge(int a,int b,int c){
nxt[++cnt]=fir[a];to[cnt]=b;fir[a]=cnt;val[cnt]=c;
} int tot,rt[maxm],key[maxm],lik[maxm],ch[maxm][],dep[maxm];
int ans[maxn],dis[maxn],add[maxm]; void Add(int x,int d){
if(!x)return;
key[x]+=d;
add[x]+=d;
} void Push_down(int x){
Add(ch[x][],add[x]);
Add(ch[x][],add[x]);
add[x]=;
} int Merge(int x,int y){
if(!x||!y)return x|y;
if(key[x]>key[y])swap(x,y);
Push_down(x);
ch[x][]=Merge(ch[x][],y);
if(dep[ch[x][]]<dep[ch[x][]])
swap(ch[x][],ch[x][]);
dep[x]=dep[ch[x][]]+;
return x;
} void Delete(int node){
Push_down(rt[node]);
rt[node]=Merge(ch[rt[node]][],ch[rt[node]][]);
} int ID[maxn],end[maxn],id; void DFS(int node){
ID[node]=++id;
for(int i=fir[node];i;i=nxt[i])
if(dis[to[i]]==dis[node]+val[i])
DFS(to[i]);
end[node]=id;
} void Solve(int node){
for(int i=fir[node];i;i=nxt[i]){
if(dis[to[i]]==dis[node]+val[i]){
Solve(to[i]);
Add(rt[to[i]],val[i]);
rt[node]=Merge(rt[node],rt[to[i]]);
}
else{
if(dis[to[i]]+val[i]==dis[node])continue;
if(ID[to[i]]<=end[node]&&ID[to[i]]>=ID[node])continue;
key[++tot]=dis[to[i]]+val[i];lik[tot]=to[i];
rt[node]=Merge(rt[node],tot);
}
}
while(rt[node]&&ID[lik[rt[node]]]<=end[node]&&ID[lik[rt[node]]]>=ID[node]){
Delete(node);
}
if(rt[node])
ans[node]=key[rt[node]];
}
struct Node{
int d,n;
Node(int d_=,int n_=){
d=d_;n=n_;
}
bool operator <(const Node &b)const{
return d>b.d;
}
}; priority_queue <Node,vector<Node> >q; int main(){
freopen("travel.in","r",stdin);
freopen("travel.out","w",stdout);
int n,m;
dep[]=-;
scanf("%d%d",&n,&m);
for(int i=,a,b,c;i<=m;i++){
scanf("%d%d%d",&a,&b,&c);
addedge(a,b,c);
addedge(b,a,c);
}
memset(dis,,sizeof(dis));
q.push(Node(,));dis[]=;
while(!q.empty()){
Node x=q.top();q.pop();
for(int i=fir[x.n];i;i=nxt[i]){
if(dis[x.n]+val[i]<dis[to[i]]){
dis[to[i]]=dis[x.n]+val[i];
q.push(Node(dis[to[i]],to[i]));
}
}
}
DFS();
Solve();
for(int i=;i<=n;i++)
printf("%d\n",ans[i]==?-:ans[i]);
return ;
}
数据结构(左偏树,可并堆):BNUOJ 3943 Safe Travel的更多相关文章
- bzoj2809 [Apio2012]dispatching——左偏树(可并堆)
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2809 思路有点暴力和贪心,就是 dfs 枚举每个点作为管理者: 当然它的子树中派遣出去的忍者 ...
- [note]左偏树(可并堆)
左偏树(可并堆)https://www.luogu.org/problemnew/show/P3377 题目描述 一开始有N个小根堆,每个堆包含且仅包含一个数.接下来需要支持两种操作: 操作1: 1 ...
- HDU3031 To Be Or Not To Be 左偏树 可并堆
欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - HDU3031 题意概括 喜羊羊和灰太狼要比赛. 有R次比赛. 对于每次比赛,首先输入n,m,n表示喜羊羊和灰 ...
- HDU5818 Joint Stacks 左偏树,可并堆
欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - HDU5818 题意概括 有两个栈,有3种操作. 第一种是往其中一个栈加入一个数: 第二种是取出其中一个栈的顶 ...
- BZOJ 4003: [JLOI2015]城池攻占 左偏树 可并堆
https://www.lydsy.com/JudgeOnline/problem.php?id=4003 感觉就是……普通的堆啊(暴论),因为这个堆是通过递归往右堆里加一个新堆或者新节点的,所以要始 ...
- Monkey King(左偏树 可并堆)
我们知道如果要我们给一个序列排序,按照某种大小顺序关系,我们很容易想到优先队列,的确很方便,但是优先队列也有解决不了的问题,当题目要求你把两个优先队列合并的时候,这就实现不了了 优先队列只有插入 删除 ...
- BZOJ 5494: [2019省队联测]春节十二响 (左偏树 可并堆)
题意 略 分析 稍微yy一下可以感觉就是一个不同子树合并堆,然后考场上写了一发左偏树,以为100分美滋滋.然而发现自己傻逼了,两个堆一一对应合并后剩下的一坨直接一次合并进去就行了.然鹅我这个sb把所有 ...
- [luogu3377][左偏树(可并堆)]
题目链接 思路 左偏树的模板题,参考左偏树学习笔记 对于这道题我是用一个并查集维护出了哪些点是在同一棵树上,也可以直接log的往上跳寻找根节点 代码 #include<cstdio> #i ...
- BZOJ1455 罗马游戏 左偏树 可并堆
欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ1455 题意概括 n个人,2种操作. 一种是合并两个人团,一种是杀死某一个人团的最弱的人. 题解 左 ...
随机推荐
- Python之路【第十七篇】:Django【进阶篇】
Python之路[第十七篇]:Django[进阶篇 ] Model 到目前为止,当我们的程序涉及到数据库相关操作时,我们一般都会这么搞: 创建数据库,设计表结构和字段 使用 MySQLdb 来连接 ...
- Android常用组件【转】
UI相关 图片 Android-Universal-Image-Loader:com.nostra13.universalimageloader:异步加载.缓存.显示图片 ImageLoader:co ...
- Less 关于css hack的写法
由于工作需要,最近一直在弄css转写less,遇到最多的问题就是 hack的写法,一些IE的hack,less不支持编译: 常见的不支持的hack如下: IE的滤镜写法 \9\0 IE8部分支持 ...
- 实训第一天--增删改查加hibernate+搭建环境常见问题
1. 搭建环境 安装 1)谷歌浏览器 2)jdk-7u67-windows-i586.exe 3)Tomcat7 4)NavicatforMySQL 两种方式: ftp://172.21.95 ...
- Unity3D 相机跟随主角移动
这里给主相机绑定一个脚本. 脚本写为: using UnityEngine; using System.Collections; public class camerafollow : MonoBeh ...
- Linux命令:cat命令详解
概述:查看文件内容,连接文件,重定向输出到文件 1.查看整个文件 2.cat > filename 创建文件 3.合并输出到文件 1.查看文件(单个或者多个) cat demo.txt 2.创建 ...
- Elasticsearch学习2--Elasticsearch数据类型简介
1.Elasticsearch 是 面向文档型数据库,这意味着它存储的是整个对象或者 文档,它不但会存储它们,还会为他们建立索引,这样你就可以搜索他们了.你可以在 Elasticsearch 中索引. ...
- SGU 146.The Runner
时间限制:0.25s 空间限制:4M 题意: 一个人在一个周长为L的圆上跑,每个时间段(Ti)的速度(Vi)不一样,问最后他离起点的圆弧距离,周长是个有四位小数的浮点数,其它全是整数. Solutio ...
- SGU 152.Making round
不断向下取直到,忽略的数累计到一个百分比,给当前百分比加1. 这道题要避免处理浮点数,用余数来处理,不然会wa 9 #include <iostream> #include <cma ...
- Codeforces 551C GukiZ hates Boxes(二分)
Problem C. GukiZ hates Boxes Solution: 假设最后一个非零的位置为K,所有位置上的和为S 那么答案的范围在[K+1,K+S]. 二分这个答案ans,然后对每个人尽量 ...