dij+堆优化

写这个dij+堆优化的原因是有些地方卡SPFA,只能搞这个;

香甜的奶油:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<string>
 5 #include<cstdlib>
 6 #include<ctime>
 7 #include<vector>
 8 #include<algorithm>
 9 #include<queue>
10 using namespace std;
11 #define LL long long
12 const int maxn=820;
13 const int inf=1000000000;
14 int d[maxn],vis[maxn],n,m,p,b[maxn];
15 struct node{
16     int y,next,v;
17 }e[5000];
18 int linkk[maxn],len=0;
19 void insert(int x,int y,int v){
20     e[++len].y=y;
21     e[len].next=linkk[x];
22     linkk[x]=len;
23     e[len].v=v;
24 }
25 typedef pair<int,int> pii;
26 priority_queue<pii,vector<pii>,greater<pii> > q;
27 int dij(int s){
28     while(!q.empty())q.pop();
29     q.push(make_pair(0,s));
30     memset(d,10,sizeof(vis));d[s]=0;
31     memset(vis,0,sizeof(vis));
32     while(!q.empty()){
33         int v=q.top().first;
34         int x=q.top().second;
35         q.pop();
36         vis[x]=1;
37         for(int i=linkk[x];i;i=e[i].next){
38             if(vis[e[i].y])continue;
39             if(d[e[i].y]>v+e[i].v){
40                 d[e[i].y]=v+e[i].v;
41                 q.push(make_pair(d[e[i].y],e[i].y));
42             }
43         }
44     }
45     int ans=0;
46     for(int i=1;i<=n;i++)ans+=d[b[i]];
47     return ans;
48 }
49 void init(){
50     scanf("%d%d%d",&n,&p,&m);//cow,muchang,daolu
51     for(int i=1;i<=n;i++)scanf("%d",&b[i]);
52     int x,y,v;
53     for(int i=1;i<=m;i++){
54         scanf("%d%d%d",&x,&y,&v);
55         insert(x,y,v);insert(y,x,v);
56     }
57 }
58 void work(){
59     int minn=inf;
60     for(int i=1;i<=p;i++)minn=min(minn,dij(i));
61     cout<<minn<<endl;
62 }
63 int main(){
64     //freopen("1.in","r",stdin);
65     //freopen("1.out","w",stdout);
66     init();
67     work();
68 }

最后的结果是这种情况下的dij跑得比spfa慢不少;

当然可能是我用了stl,常数太大;

spfa和堆优化dij的唯一区别是一个用队列,需要多次迭代找出最优(也可能直接就找到最优值),一个用堆,可以直接找到一个不确定的点的最优值,但由于用了堆,复杂度要乘一个log;

其他的基本一样的;

spfa稀疏图好用,dij稠密图好用,上面的那道题就是个例子;

时间: 2024-10-11 16:55:01

dij+堆优化的相关文章

hdu1245+dij,堆优化

有一片100*100的湖泊,中心坐标(0,0),即湖泊右上角的坐标是(50,50),湖泊中间有一片以(0,0)为圆心,15为直径的圆形陆地.现有一个人在陆地,湖泊中散布着一些点可以踩,这个人要利用这些点跳到岸上,求最短路径和最短路径下的最短步数. spfa莫名其妙的超时,dij+堆优化反而能过...可能spfa更适合有向图吧. 使用vector<vector<node> > g这种双重结构时,最好先g.resize(N)设置一下容量,否则直接插入会出错. 1 #include<

迪杰斯特拉算法(Dijkstra) (基础dij+堆优化) BY:优少

首先来一段百度百科压压惊... 迪杰斯特拉算法(Dijkstra)是由荷兰计算机科学家狄克斯特拉于1959 年提出的,因此又叫狄克斯特拉算法.是从一个顶点到其余各顶点的最短路径算法,解决的是有权图中最短路径问题.迪杰斯特拉算法主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止. 让我来翻译一下:Dijkstra可以求出一个点到一个图中其他所有节点的最短路径,故也称对于单源最短路径的一种解法 算法实现步骤: a.初始时,只包括源点,即S = {v},v的距离为0.U包含除v以外的其他顶点,即

单源最短路径(dij+堆优化)

单源最短路径的模板题,感谢同学余能的帮助~ #include<bits/stdc++.h> #define inf 2147483647 using namespace std; bool book [200004]; int cnt=0; int head[200020]; int n,m,qq; struct Edge { int to,next,w; }e[2000005]; struct Dis { int to,w; }dis[20000]; struct cmp1 { bool o

【洛谷P1462】【二分+堆优化dij】

题目描述 在艾泽拉斯,有n个城市.编号为1,2,3,...,n. 城市之间有m条双向的公路,连接着两个城市,从某个城市到另一个城市,会遭到联盟的攻击,进而损失一定的血量. 每次经过一个城市,都会被收取一定的过路费(包括起点和终点).路上并没有收费站. 假设1为暴风城,n为奥格瑞玛,而他的血量最多为b,出发时他的血量是满的. 歪嘴哦不希望花很多钱,他想知道,在可以到达奥格瑞玛的情况下,他所经过的所有城市中最多的一次收取的费用的最小值是多少. 题目分析 题目说了那么多,其实就是让求在角色不死亡的情况

Dij的堆优化

#include<algorithm> #include<iostream> #include<cstdio> #include<cstring> #include<queue> #define M 100000 #define pa pair<int,int>//优先比较第一个元素 using namespace std; int d[M],n,m,cnt,head[M],next[M],u[M],dis[M],num,s,t; b

bzoj3040 最短路+配对堆优化

3040: 最短路(road) Time Limit: 60 Sec  Memory Limit: 200 MBSubmit: 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条边采用如下方式生成

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

poj 3013 Big Christmas Tree (dij+优先队列优化 求最短路)

模板 题意:给你一个图,1总是为根,每个边有单位价值,每个点有权重. 每条边的价值 = sum(后继节点权重)*边的单位价值. 求树的最小价值,即构成一棵树的n-1条边的最小价值. 算法: 1.因为每个边的价值都要乘以后来访问的节点的权重,而走到后来访问的点必经过这条边. 实际上总价值就是  到每个点的最短路径*这个点的权重. 2.但是这个题 数据量真的太大了,50000个点,50000条边. 写普通的dij算法tle. 必须加优先队列优化- - 据说spfa也能过,但是spfa算法不稳定- -

【Dijstra堆优化】HDU 3986 Harry Potter and the Final Battle

http://acm.hdu.edu.cn/showproblem.php?pid=3986 [题意] 给定一个有重边的无向图,T=20,n<=1000,m<=5000 删去一条边,使得1~n的最短路最长 求最短路最长是多少 [思路] 一定是删最短路上的边 可以先跑一个Dijkstra,求出最短路,然n后枚举删边 朴素的Dijkstra为n^2,枚举删边(n条)需要的总时间复杂度是n^3 堆优化Dijkstra(nlogn),总复杂度为n^2logn 有多重边,用邻接矩阵不方便,用邻接表方便,