您的位置:首页 > 其它

优先队列优化Dijkstra-hdu2066

2017-07-24 13:29 309 查看

Dijkstra

Dijkstra算法适用于边权为正的情况,用于计算正权图上的单源最短路(Single-Source Shortest Paths,SSSP),即从单个源点出发,到所有结点的最短路。该算法同时适用于有向图和无向图。时间复杂度为O(n^2),n是节点数。

算法思想:

首先初始化dist为INF=0x3f3f3f3f,dist[源点]=0,然后循环n次,在所有未标号的结点中,选出dist值最小的结点x,给结点x标记,对从x结点出发的所有边(x,y)更新dist[y]。

该算法也能很方便的打印出结点1到所有结点的最短路本身,只需在更新dist[y]时用path数组维护从最短路到该结点的父结点的下标即可。

现在算法竞赛中可能一般的Dijkstra写法会被卡时间,n^2的复杂度还是很高的。所以我们写正权的最短路问题最好还是用邻接表+堆优化(优先队列优化)的Dijkstra。

Dijksta算法中,如果我们采用的是邻接矩阵来存边,空间浪费大,时间复杂度也高,所以我们考虑优化它,采用邻接表来存储,其次我们可以用优先队列来排序大小,其时间复杂度大大降低。

我看网上有些人是自己手写小根堆实现,这当然是更好的。我问了下学长,应该是不会卡手写小根堆和STL优先队列之间的差距,而优先队列的写法更简洁,所以我还是选优先队列来写。

我以hdu2066为模板来实现优先队列优化的Dijkstra

hdu2066

这题不是很难,把根看成源点,将其到车站的距离置为0,然后直接Dijkstra,最后取所有终点的最小值即可。

具体优化过程和题解看代码注释

#include <bits/stdc++.h>
using namespace std;

const int INF = 0x3f3f3f3f;
const int maxn = 1e3+5;
int t,s,d;

struct Edge{
int to,len; //存储边信息,to是到的点,len是时间
};
vector<Edge> edge[maxn];  //edge[i]记录与i点相连的边
//把i点和dist[i]打包放入优先队列。
//这里要注意pair是按照第一个元素的大小排序,如果相同才按照第二个,所以我们要把dist[i]包装在第一个元素上。
typedef pair<int,int> P;
int dist[maxn];  //dist[i]记录从源点到i点的最短时间

void init()  //初始化
{
for(int i=0;i<maxn;i++) edge[i].clear();
memset(dist,INF,sizeof(dist));
}

void Dijkstra()
{
priority_queue<P,vector<P>,greater<P> >pq;
P p;
Edge tmp;
dist[0]=0;  //源点dist置0
pq.push(P(0,0)); //源点加入队列
while(!pq.empty())
{
p = pq.top(),pq.pop();
int u = p.second; //得到当前节点
for(int i=0;i<edge[u].size();i++)  //遍历与当前节点相连的节点
{
tmp = edge[u][i];
if(dist[tmp.to]>dist[u]+tmp.len)
{
dist[tmp.to] = dist[u]+tmp.len;  //更新
pq.push(P(dist[tmp.to],tmp.to));
}
}
}
}

int main()
{
while(~scanf("%d%d%d",&t,&s,&d))
{
init();
int a,b,c;
Edge tmp;
while(t--)
{
scanf("%d%d%d",&a,&b,&c);
//建边
tmp.to = b,tmp.len = c;
edge[a].push_back(tmp);
tmp.to = a,tmp.len = c;
edge[b].push_back(tmp);
}
while(s--)
{
scanf("%d",&a);
//源点(家)和车站相连
tmp.to = a,tmp.len = 0;
edge[0].push_back(tmp);
tmp.to = 0,tmp.len = 0;
edge[a].push_back(tmp);
}
Dijkstra();
int ans = INF;
while(d--)
{
scanf("%d",&a);
if(dist[a]<ans) ans = dist[a];  //得到所有终点的最短时间
}
printf("%d\n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: