Codeforces 464E The Classic Problem (最短路 + 主席树 + hash)
这个题加深了我对主席树的理解,是个好题。每次更新某个点的距离时,是以之前对这个点的插入操作形成的线段树为基础,在O(logn)的时间中造出了一颗新的线段树,相比直接创建n颗线段树更省时间。比较的时候二分比较,为了加快比较给每个点设置一个hash值。
代码:
#include <bits/stdc++.h>
using namespace std;
const unsigned long long P = 13331;
const int mod = 1000000007;
const int maxn = 100010; int head[maxn], Next[maxn * 2], edge[maxn * 2], ver[maxn * 2];
int tot, tote;
int b[maxn * 2], pre[maxn];
int mx, dis[maxn];
bool vis[maxn];
int Stack[maxn], Top; void add(int x, int y, int z) {
ver[++tote] = y;
edge[tote] = z;
Next[tote] = head[x];
head[x] = tote;
}
struct SegementTree {
int ls, rs;
int sum;
unsigned long long hash;
}tr[maxn * 200]; void pushup(int x) {
tr[x].sum = tr[tr[x].ls].sum + tr[tr[x].rs].sum;
unsigned long long tmp1 = tr[tr[x].ls].hash, tmp2 = tr[tr[x].rs].hash;
tr[x].hash = (((tmp1 * P + tmp2) ^ tmp1) * P ^ tmp2) * P;
} void insert(int &now, int l, int r, int pos) {
int p = now;
now = ++tot;
tr[now] = tr[p];
if(l == r) {
tr[now].sum = 1;
tr[now].hash = l + P;
return;
}
int mid = (l + r) >> 1;
if(pos <= mid) insert(tr[now].ls, l, mid, pos);
else insert(tr[now].rs, mid + 1, r, pos);
pushup(now);
} void del(int &now, int l, int r, int ql, int qr) {
if(l >= ql && r <= qr) {
now = 0;
return;
}
int p = now;now = ++tot;
tr[now] = tr[p];
int mid = (l + r) >> 1;
if(ql <= mid) del(tr[now].ls, l, mid, ql, qr);
if(qr > mid) del(tr[now].rs, mid + 1, r, ql, qr);
pushup(now);
} int query(int now, int l, int r, int pos) {
if(l == r) {
if(tr[now].sum == 0) return l;
return -1;
}
int mid = (l + r) >> 1;
if(pos > mid) return query(tr[now].rs, mid + 1, r, pos);
int ans = query(tr[now].ls, l, mid, pos);
if(ans != -1) return ans;
return query(tr[now].rs, mid + 1, r, pos);
} int add(int now, int pos) {
int p = query(now, 0, mx, pos);
if(p > pos) del(now, 0, mx, pos, p - 1);
insert(now, 0, mx, p);
return now;
} int get_sum(int now, int l, int r) {
int mid = (l + r) >> 1;
if(now == 0) return 0;
if(l == r) return b[l];
return (get_sum(tr[now].ls, l, mid) + get_sum(tr[now].rs, mid + 1, r)) % mod;
} bool cmp(int x, int y, int l, int r) {
if(l == r) return tr[x].sum >= tr[y].sum;
int mid = (l + r) >> 1;
if(tr[tr[x].rs].hash != tr[tr[y].rs].hash)
return cmp(tr[x].rs, tr[y].rs, mid + 1, r);
else return cmp(tr[x].ls, tr[y].ls, l, mid);
} struct node {
int x, y;
bool operator < (const node& rhs) const {
return cmp(x, rhs.x, 0, mx);
}
}; priority_queue<node> q; void dijkstra(int s) {
dis[s] = ++tot, q.push((node){dis[s], s});
while(!q.empty()) {
node tmp = q.top();
q.pop();
if(vis[tmp.y]) continue;
vis[tmp.y] = 1;
int x = tmp.y;
for (int i = head[x]; i; i = Next[i]) {
int y = ver[i], z = add(dis[x], edge[i]);
if(!dis[y] || !cmp(z, dis[y], 0, mx)) {
pre[y] = x;
dis[y] = z;
q.push((node){z, y});
}
}
}
} void print(int x, int deep) {
if(x == 0) {
printf("%d\n", deep);
return;
}
print(pre[x], deep + 1);
printf("%d ", x);
}
int main() {
int n, m, x, y, z, s, t;
scanf("%d%d", &n, &m);
for (int i = 1; i <= m; i++) {
scanf("%d%d%d", &x, &y, &z);
add(x, y, z);
add(y, x, z);
mx = max(mx, z);
}
b[0] = 1;
mx += 20;
for (int i = 1; i <= mx; i++) {
b[i] = (b[i - 1] << 1) % mod;
}
scanf("%d%d", &s, &t);
dijkstra(s);
if(dis[t] == 0) printf("-1\n");
else {
printf("%d\n", get_sum(dis[t], 0, mx));
while(t) {
Stack[++Top] = t;
t = pre[t];
}
printf("%d\n", Top);
while(Top) {
printf("%d ", Stack[Top]);
Top--;
}
}
}
Codeforces 464E The Classic Problem (最短路 + 主席树 + hash)的更多相关文章
- [Codeforces 464E] The Classic Problem(可持久化线段树)
[Codeforces 464E] The Classic Problem(可持久化线段树) 题面 给出一个带权无向图,每条边的边权是\(2^{x_i}(x_i<10^5)\),求s到t的最短路 ...
- Codeforces 464E The Classic Problem(主席树+最短路+哈希,神仙题)
题目链接 题意:给出一张 \(n\) 个点 \(m\) 条边的无向图,第 \(i\) 条边连接 \(u_i,v_i\),边权为 \(2^{w_i}\),求 \(s\) 到 \(t\) 的最短路. \( ...
- CodeForces 464E The Classic Problem | 呆克斯歘 主席树维护高精度
题意描述 有一个\(n\)点\(m\)边的无向图,第\(i\)条边的边权是\(2^{a_i}\).求点\(s\)到点\(t\)的最短路长度(对\(10^9 + 7\)取模). 题解 思路很简单--用主 ...
- Codeforces 464E. The Classic Problem
题目大意 给定一张$n$个点, $m$条边的无向图,求$S$ 到$T$的最短路,其中边权都是$2^k$的形式$n,m,k<=10^5$,结果对$10^9+7$取模 题解 大佬好厉害 跑一边dij ...
- Codeforces 464E #265 (Div. 1) E. The Classic Problem 主席树+Hash
E. The Classic Problem http://codeforces.com/problemset/problem/464/E 题意:给你一张无向带权图,求S-T的最短路,并输出路径.边权 ...
- CF 464E The Classic Problem
补一补之前听课时候的题. 考虑使用dij算法求最短路,因为边权存不下,所以考虑用主席树维护二进制位,因为每一次都只会在一个位置进行修改,所以可以暴力进位,这样均摊复杂度是对的. <算法导论> ...
- codeforces gym #101161E - ACM Tax(lca+主席树)
题目链接: http://codeforces.com/gym/101161/attachments 题意: 给出节点数为$n$的树 有$q$次询问,输出$a$节点到$b$节点路程中,经过的边的中位数 ...
- 【bzoj3218】a+b Problem 最小割+主席树
数据范围:$n≤5000$,$a,l,r≤10^9$,$b,w,p≤2\times 10^5$. 我们考虑一种暴力的最小割做法: 首先令$sum=\sum\limits_{i=1}^{n} b_i+w ...
- HDU 4729 An Easy Problem for Elfness 主席树
题意: 给出一棵树,每条边有一个容量. 有若干次询问:\(S \, T \, K \, A \, B\),求路径\(S \to T\)的最大流量. 有两种方法可以增大流量: 花费\(A\)可以新修一条 ...
随机推荐
- python3中的unicode_escape
一. 响应的两种方式 在使用python3的requests模块时,发现获取响应有两种方式 其一,为文本响应内容, r.text 其二,为二进制响应内容,r.content 在<Python学习 ...
- Linux tar命令总结
压缩 tar –cvf jpg.tar *.jpg 将目录里所有jpg文件打包成tar.jpg tar –czf jpg.tar.gz *.jpg 将目录里所有jpg文件打包成jpg.tar后, ...
- OpenCV - opencv3 图像处理 之 图像缩放( python与c++实现 )
转自:https://www.cnblogs.com/dyufei/p/8205121.html 一. 主要函数介绍 1) 图像大小变换 cvResize () 原型: voidcvResize(co ...
- 2017.10.4北京清北综合强化班DAY4
财富(treasure) Time Limit:1000ms Memory Limit:128MB 题目描述 LYK有n个小伙伴.每个小伙伴有一个身高hi. 这个游戏是这样的,LYK生活的环境是以 ...
- 前端项目使用module.exports文件一定要Webpack编译吗?请问gulp可以编译这种文件吗
import引入类似这种文件,一定要用webpack去编译吗 module.pxports 是CMD规范的一个全局函数,功能是当前模块对外提供接口.require可以直接使用这个接口.例子: echo ...
- windows10环境下运行Debug
1. 什么是Debug? Debug是DOS.Windows都提供的实模式(8086方式)程序的调试工具. 使用它,可以查看CPU各种寄存器中的内容.内存的情况和在机器码级别跟踪程序的运行. 2. 常 ...
- linux下查找命令两则
由于本人不会阅读man手册,因此需要几下两个常用的查找命令: (1)在某个目录及其子目录查找某个文件并打印完整路径: find ./ -name "assertions.h" -e ...
- My97DatePicker 和转换 数据库中日期(/Date(1351699200000)/) 的格式
一 转换 数据库中日期(/Date(1351699200000)/) 的格式: C#中转换日期格式 var date=com.CREATEDATETIME.ToString(); JavaScrip ...
- ISE(Iris Server Engine)是一个基于现代C++的跨平台(Linux和Windows)框架
ISE(Iris Server Engine)是一个基于现代C++的跨平台(Linux和Windows)的高性能多线程并发网络服务器程序框架.它封装了琐碎的socket以及各种操作系统APIs,以面向 ...
- java代码继承难点。构造方法的调用
总结:子类默认调用父类的无参构造方法.重写时,父类方法将被覆盖,不被调用,在子类中可以使用super.方法():可以实现 运行显示: evente.x:55 evente.x:55 B.y:57 pa ...