bzoj3040 最短路+配对堆优化

3040: 最短路(road)

Time Limit: 60 Sec  Memory Limit: 200 MB
Submit: 1859  Solved: 564
[Submit][Status][Discuss]

Description

N个点,M条边的有向图,求点1到点N的最短路(保证存在)。
1<=N<=1000000,1<=M<=10000000

Input

第一行两个整数N、M,表示点数和边数。
第二行六个整数T、rxa、rxc、rya、ryc、rp。

前T条边采用如下方式生成:
1.初始化x=y=z=0。
2.重复以下过程T次:
x=(x*rxa+rxc)%rp;
y=(y*rya+ryc)%rp;
a=min(x%n+1,y%n+1);
b=max(y%n+1,y%n+1);
则有一条从a到b的,长度为1e8-100*a的有向边。

后M-T条边采用读入方式:
接下来M-T行每行三个整数x,y,z,表示一条从x到y长度为z的有向边。

1<=x,y<=N,0<z,rxa,rxc,rya,ryc,rp<2^31

Output

一个整数,表示1~N的最短路。

Sample Input

3 3
0 1 2 3 5 7
1 2 1
1 3 3
2 3 1

Sample Output

2

请采用高效的堆来优化Dijkstra算法。

第一眼以为是裸堆优化dijkstra

看到hzwer题解发现要用奇怪的堆优化

据说priority_queue里有五大堆,这里用的是配对堆

 1 #include <stdio.h>
 2 #include <ext/pb_ds/priority_queue.hpp>
 3 #include <string.h>
 4 #define inf 10000000000000000LL
 5 #include <algorithm>
 6 using namespace std;
 7 typedef pair<long long , int > pii;
 8 //priority_queue <pii, vector<pii>, greater<pii > > q;
 9 using namespace __gnu_pbds;
10 typedef __gnu_pbds::priority_queue <pii,  greater<pii >, pairing_heap_tag > heap;
11 heap::point_iterator id[1000005];
12 struct node
13 {
14     int u, v, w, next;
15 }a[10000005];
16 int tot, n, m, rxa, rxc, rya, ryc;
17 long long dis[1000005];
18 int rp, T, first[1000005];
19 void addedge(int st, int end, int val)
20 {
21     a[++tot].u = st;a[tot].v = end;a[tot].w = val;
22     a[tot].next =first[st];first[st] = tot;
23 }
24 int dij(int S)
25 {
26     heap q;
27     for (int i = 1; i <= n; i++)dis[i] = inf;
28     id[1] = q.push(make_pair(0, 1));
29     dis[1] = 0;
30     while (!q.empty())
31     {
32         int u = q.top().second;q.pop();
33         for (int e = first[u]; e != -1; e = a[e].next)
34         {
35             int v = a[e].v;
36             if (dis[u] + a[e].w < dis[v])
37             {
38                 dis[v] = dis[u] + a[e].w;
39                 if (id[v] != 0)
40                     q.modify(id[v], make_pair(dis[v], v));
41                 else id[v] = q.push(make_pair(dis[v], v));
42             }
43         }
44     }
45 }
46 int main()
47 {
48     scanf("%d %d", &n, &m);
49     scanf("%d %d %d %d %d %d", &T, &rxa, &rxc, &rya, &ryc, &rp);
50     int x , y , z , A, B;
51     x = y = z = 0;
52     memset(first, -1, sizeof(first));
53     for (int i = 1; i <= T; i++)
54     {
55         x = ((long long )x*rxa + rxc) % rp;
56         y = ((long long )y*rya + ryc) % rp;
57         A = min(x%n+1, y%n+1);
58         B = max(y%n+1, y%n+1);
59         addedge(A, B, 100000000 - 100*A);
60      }
61      for (int i = 1; i <= m - T; i++)
62      {
63         scanf("%d %d %d", &x, &y, &z);
64         addedge(x, y, z);
65      }
66      dij(1);
67      printf("%lld\n", dis[n]);
68 }
时间: 2024-08-01 10:41:26

bzoj3040 最短路+配对堆优化的相关文章

BZOJ3040 最短路 (堆优化dijkstra)

这题不是裸的最短路么?但是一看数据范围就傻了.点数10^6,边数10^7.这个spfa就别想了(本来spfa就是相当不靠谱的玩意),看来是要用堆优化dijkstra了.但是,平时写dijkstra时为了偷懒直接用的STL的priority_queue,没办法改变权值,所以都是直接把pair压进堆里.然后时间复杂度O(mlogm),空间复杂度O(m),不靠谱.手写二叉堆?改变权值是O(logn)的,所以时间复杂度O(mlogn),空间复杂度O(n),还是要T.看来是需要一种比较牛逼的堆了. Fib

配对堆优化Dijkstra算法小记

关于配对堆的一些小姿势: 1.配对堆是一颗多叉树. 2.包含优先队列的所有功能,可用于优化Dijkstra算法. 3.属于可并堆,因此对于集合合并维护最值的问题很实用. 4.速度快于一般的堆结构(左偏树,斜堆,随机堆--),具体时间复杂度: 合并(Merge):$O(1)$: 插入(Insert/Push):$O(1)$: 修改值(Change):$O(1) \sim O(\log n)$: 取出维护的最值(Top):$O(1)$: 弹出堆顶元素(Pop):$O(\log n)$: 我们依然拿洛

BZOJ 3040 最短路(road) 堆优化Dijkstra

题目大意:最短路. 思路:最短路. 贴一份比较高效的堆优化Dij模板吧. CODE: #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define _MAX 1000010 #define MAX 10000010 using namespace std; #define min(a,b) ((a) < (b) ? a:b) long long

[Usaco2010 Feb]Chocolate Giving 最短路dijkstra+堆优化

本人水平有限,题解不到为处,请多多谅解 本蒟蒻谢谢大家观看 题目:传送门 最短路板子题:迪杰斯特拉+堆优化 注意:因为我建的是大根堆,所以要将距离取负,再存入大根堆堆中,这样队首就是最小值 直接套模板即可 code: 1 #include<bits/stdc++.h> 2 #define inf 0x3f3f3f3f 3 #pragma GCC optimize(3) 4 const int N=50005; 5 const int M=200002; 6 using namespace st

hdu 2544 单源最短路问题 dijkstra+堆优化模板

最短路 Time Limit: 5000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 41168    Accepted Submission(s): 17992 Problem Description 在每年的校赛里.全部进入决赛的同学都会获得一件非常美丽的t-shirt.可是每当我们的工作人员把上百件的衣服从商店运回到赛场的时候,却是非常累的.所以如今他们想要寻

Bzoj 2834: 回家的路 dijkstra,堆优化,分层图,最短路

2834: 回家的路 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 62  Solved: 38[Submit][Status][Discuss] Description Input Output Sample Input 2 1 1 2 1 1 2 2 Sample Output 5 HINT N<=20000,M<=100000 Source dijkstra+堆优化+分层图 把所有的横向和纵向分开看.跑最短路即可. 注意:N这么大,不能写

dijkstra(最短路)和Prim(最小生成树)下的堆优化

最小堆: down(i)[向下调整]:从第k层的点i开始向下操作,第k层的点与第k+1层的点(如果有)进行值大小的判断,如果父节点的值大于子节点的值,则修改,并继续对第k+1层与第k+2层的点进行判断和修改,否则不修改,且退出.当点向下移动到树的最后一层,没有子节点供判断与修改,停止操作. 树最多有log(n) 层[log(n)=log2n,一般省略数字2],时间复杂度log(n)次. up(i)[向上调整]:同理,时间复杂度log(n)次. 1.求n个数进行排序: I.建树(n/2次down)

【堆优化Dijkstra+字典序最短路方案】HDU1385-Minimum Transport Cost

[题目大意] 给出邻接矩阵以及到达各个点需要付出的代价(起点和终点没有代价),求出从给定起点到终点的最短路,并输出字典序最小的方案. [思路] 在堆优化Dijkstra中,用pre记录前驱.如果新方案和旧方案相等,比较两个方案的字典序. [坑点] 我先求出了最短路(包括终点要付出代价),输出的时候再减去终点的代价. 有可能会给出S==T的情况--在这种情况下,最短路就是0,减去代价要变成负数了QAQ所以要特判一下.坑了好几个小时orz 1 #include<iostream> 2 #inclu

dijkstra(迪杰斯特拉)最短路算法的堆优化

dijkstra(迪杰斯特拉)最短路算法是一种时间复杂度经过严格证明的最短路算法. 优化在于每次取最小值的时候采用堆优化,但是在最短路松弛过程中,dist是不断修改的,所以,为了能使复杂度降到O(nlogn),dist修改的同时,在堆中也要修改. 注意dijkstra(迪杰斯特拉)最短路算法只能用于正权边. 1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algo