补一补之前听课时候的题。

考虑使用dij算法求最短路,因为边权存不下,所以考虑用主席树维护二进制位,因为每一次都只会在一个位置进行修改,所以可以暴力进位,这样均摊复杂度是对的。

《算法导论》给了证明:对于一个有$k$位的二进制计数器,假设每一次都从第0位$+1$,那么我们发现执行$n$次加法之后,发现第零位会变$\left \lfloor \frac{n}{1} \right \rfloor$次,第一位会变$\left \lfloor \frac{n}{2} \right \rfloor$次...而第$n$位会变$\left \lfloor \frac{n}{2^n} \right \rfloor$次,这样子所有的操作次数就相当于$\sum_{i = 0}^{k - 1}\left \lfloor \frac{i}{2^i} \right \rfloor < n * \sum_{i = 0}^{\infty}\frac{1}{2^i} = 2n$,所以最坏情况下的时间为$O(n)$,每一次操作的均摊时间复杂度为$O(n) / n = O(1)$。

这样子只需要借助主席树写一个时间为$O(log)$的$cmp$函数就可以用堆优化dijkskra了,遇到进位就在线段树上暴力搞一搞,反正复杂度是对的。

数太大了直接用题目中给的$seed = 2, Mod = 1e9 + 7$的哈希哈希一下就好了。

时间复杂度$O(nlog^2n)$。

感觉就像是对着大佬的题解抄了一遍。

Code:

#include <cstdio>
#include <cstring>
#include <queue>
#include <cstdlib>
using namespace std; const int N = 1e5 + ;
const int P = 1e9 + ; int n, m, st, ed, lim = , bin[N << ];
int tot = , head[N], pre[N]; struct Edge {
int to, nxt, val;
} e[N << ]; inline void add(int from, int to, int val) {
e[++tot].to = to;
e[tot].val = val;
e[tot].nxt = head[from];
head[from] = tot;
} inline void read(int &X) {
X = ; char ch = ; int op = ;
for(; ch > ''|| ch < ''; ch = getchar())
if(ch == '-') op = -;
for(; ch >= '' && ch <= ''; ch = getchar())
X = (X << ) + (X << ) + ch - ;
X *= op;
} inline void chkMax(int &x, int y) {
if(y > x) x = y;
} namespace PSegT {
struct SegNode {
int lc, rc, w;
} s[N * ]; int nodeCnt, root[N]; #define mid ((l + r) >> 1) bool cmp(int x, int l, int r, int y) {
if(l == r) return s[x].w > s[y].w;
if(s[s[x].rc].w == s[s[y].rc].w) return cmp(s[x].lc, l, mid, s[y].lc);
else return cmp(s[x].rc, mid + , r, s[y].rc);
} bool modify(int &x, int l, int r, int pos, int y) {
s[x = ++nodeCnt] = s[y];
if(l == r) {
s[x].w = s[y].w ^ ;
return s[y].w;
} int res;
if(pos > mid) res = modify(s[x].rc, mid + , r, pos, s[y].rc);
else {
res = modify(s[x].lc, l, mid, pos, s[y].lc);
if(res) res = modify(s[x].rc, mid + , r, mid + , s[y].rc);
} s[x].w = (1LL * s[s[x].rc].w * bin[mid - l + ] % P + s[s[x].lc].w) % P;
return res;
} } using namespace PSegT; struct Node {
int x, rt; bool operator < (const Node &oth) const {
return cmp(rt, , lim, oth.rt);
} };
priority_queue <Node> Q; void dfs(int x, int dep) {
if(x == st) {
printf("%d\n%d ", dep, x);
return;
} dfs(pre[x], dep + );
printf("%d ", x);
} inline void out() {
printf("%d\n", s[root[ed]].w);
dfs(ed, );
printf("\n");
exit();
} int main() {
read(n), read(m);
for(int x, y, v, i = ; i <= m; i++) {
read(x), read(y), read(v);
add(x, y, v), add(y, x, v);
chkMax(lim, v);
}
lim += ;
read(st), read(ed); for(int i = bin[] = ; i <= lim; i++)
bin[i] = 1LL * bin[i - ] * % P; nodeCnt = ;
Q.push((Node) {st, root[st]});
for(; !Q.empty(); ) {
Node now = Q.top(); Q.pop();
if(now.rt != root[now.x]) continue;
if(now.x == ed) out();
for(int i = head[now.x]; i; i = e[i].nxt) {
int y = e[i].to, v;
modify(v, , lim, e[i].val, root[now.x]);
if(!root[y] || cmp(root[y], , lim, v)) {
root[y] = v;
Q.push((Node) {y, root[y]});
pre[y] = now.x;
}
}
} puts("-1");
return ;
}

CF 464E The Classic Problem的更多相关文章

  1. [Codeforces 464E] The Classic Problem(可持久化线段树)

    [Codeforces 464E] The Classic Problem(可持久化线段树) 题面 给出一个带权无向图,每条边的边权是\(2^{x_i}(x_i<10^5)\),求s到t的最短路 ...

  2. CodeForces 464E The Classic Problem | 呆克斯歘 主席树维护高精度

    题意描述 有一个\(n\)点\(m\)边的无向图,第\(i\)条边的边权是\(2^{a_i}\).求点\(s\)到点\(t\)的最短路长度(对\(10^9 + 7\)取模). 题解 思路很简单--用主 ...

  3. Codeforces 464E. The Classic Problem

    题目大意 给定一张$n$个点, $m$条边的无向图,求$S$ 到$T$的最短路,其中边权都是$2^k$的形式$n,m,k<=10^5$,结果对$10^9+7$取模 题解 大佬好厉害 跑一边dij ...

  4. Codeforces 464E The Classic Problem (最短路 + 主席树 + hash)

    题意及思路 这个题加深了我对主席树的理解,是个好题.每次更新某个点的距离时,是以之前对这个点的插入操作形成的线段树为基础,在O(logn)的时间中造出了一颗新的线段树,相比直接创建n颗线段树更省时间. ...

  5. Codeforces 464E The Classic Problem(主席树+最短路+哈希,神仙题)

    题目链接 题意:给出一张 \(n\) 个点 \(m\) 条边的无向图,第 \(i\) 条边连接 \(u_i,v_i\),边权为 \(2^{w_i}\),求 \(s\) 到 \(t\) 的最短路. \( ...

  6. Codeforces 464E #265 (Div. 1) E. The Classic Problem 主席树+Hash

    E. The Classic Problem http://codeforces.com/problemset/problem/464/E 题意:给你一张无向带权图,求S-T的最短路,并输出路径.边权 ...

  7. 把一个序列转换成严格递增序列的最小花费 CF E - Sonya and Problem Wihtout a Legend

    //把一个序列转换成严格递增序列的最小花费 CF E - Sonya and Problem Wihtout a Legend //dp[i][j]:把第i个数转成第j小的数,最小花费 //此题与po ...

  8. cf 633B A trivial problem

    Mr. Santa asks all the great programmers of the world to solve a trivial problem. He gives them an i ...

  9. 【dp/贪心】CF 780 (Div. 3), problem: (C) Get an Even String

    Problem - C - Codeforces 难度: 1300 input 6 aabbdabdccc zyx aaababbb aabbcc oaoaaaoo bmefbmuyw output ...

随机推荐

  1. xsl教程学习笔记

    一 . Hello world 尝试: Hello.xml: <?xml version="1.0" encoding="UTF-8"?> < ...

  2. ICE 的回调

    使用分布式计算中间件ICE到现在已经有一年多了,在这一年里里面对ICE的理解.应用比较熟悉. 使用ICE写分布式软件,确实是很方便:ICE比较稳定.可靠,调用返回速度低延迟,使用简单,学习曲线不是很陡 ...

  3. CodeForces - 896D :Nephren Runs a Cinema(卡特兰数&组合数学---比较综合的一道题)

    Lakhesh loves to make movies, so Nephren helps her run a cinema. We may call it No. 68 Cinema. Howev ...

  4. DIV设置浮动float以后下一个DIV要换行的方法

    <div style=“float:left;”> 1111111 </div> <div style=“float:left;”>222222 </div& ...

  5. spark 算子分析

    别的不说先上官网: action 这些算子中需要注意: 1.reduce 和 reduceByKey 虽说都有reduce,但是一个是action级别,一个是transformation级别,速度上会 ...

  6. java代码String创建对象数组,进行排序

    总结:String是一个类.对于字串大小比较用方法:compareTo() package com.da.ima2; public class gh { public static void main ...

  7. 校赛热身 Problem C. Sometimes Naive (状压dp)

    题解: 列举每一种3的倍数的组合,开始先求出3条边的可行解,则 六条边的可行解可以由两个三条边得来. 详见代码解析 #include<bits/stdc++.h> using namesp ...

  8. 杂项:MIME(多用途互联网邮件扩展类型)百科

    ylbtech-杂项:MIME(多用途互联网邮件扩展类型)百科 MIME(Multipurpose Internet Mail Extensions)多用途互联网邮件扩展类型.是设定某种扩展名的文件用 ...

  9. CRC 简介

    CRC wiki,历史发展,各个版本的用途 等 https://en.wikipedia.org/wiki/Cyclic_redundancy_check (apple)crc32.c /* * Th ...

  10. web编程的初步认识

    一直以后, 只知道打开浏览器, 输入网址便可以上网浏览网页, 但是当认真琢磨起这web编程的时候, 对于很多细节却是感觉很迷惑, 在慢慢的学习中, 才逐渐有了些了解. web有client/serve ...