HDU[2066] 单源最短路dijkstra算法的优先队列nlogn优化

来源:互联网 发布:win如何打开udp端口 编辑:程序博客网 时间:2024/06/06 17:37

Dijkstra算法

用来计算从一个点到其他所有点的最短路径的算法,是一种单源最短路径算法。  

算法描述: 
每次找到距离原点最近的点,并通过它对其他店进行松弛。
        每次查找需要O(n)  ,每次操作一个点需要O(n) 操作n个点时间复杂度为O(n^2)

优化后的dijkstra

        由于具有优先队列,我们可以把这个查找操作复杂度降低到O(logn)

每次操作一个点需要O(n) 操作n个点时间复杂度为O(nlogn)

具体操作为:

       每次找出距离原点最近的点入队列
       再将与它相连的点均放入队列
       每次取出队首元素判断是否标记过
       如果标记过则不可能再被其他点松弛
       如果没有标记过则标记并用它来松弛其他点

模板题 HDU2066    http://acm.hdu.edu.cn/showproblem.php?pid=2066

先将与起点相邻的点初始化 

e[0][i]=0;  vis[i]=0;

         之后进行 dijkstra

  最后维护一下到每个目的地的最小值

注意此题存在相同起始点的路径,所以记得保存最短路径(窝因为这个wa到爆炸。。。

   注意多组数据的数据重置问题

#include<iostream>#include<queue>#include<algorithm>#define maxn 1005#define inf 99999999 using namespace std;int e[maxn][maxn];int book[maxn];int vis[maxn];int n,m;struct data{int dis;int flag;data(){}    data(int a,int b){dis=a;flag=b;}friend bool operator <(data a,data b)//重载运算符{return a.dis>b.dis; }};priority_queue<data> dis;int main(){int a,b,c;int m,s,d;        int flag;int ans=inf;int want[maxn]; while(cin>>m>>s>>d){for(int i=0;i<=maxn;i++)//数据重置{  for(int j=0;j<=maxn;j++){if(i==j)e[i][j]=0;elsee[i][j]=inf;}book[i]=0; }for(int i=0;i<m;i++){cin>>a>>b>>c;if(c<e[a][b])//保存最短边{ e[a][b]=c;e[b][a]=c;}}for(int i=0;i<s;i++)//将相邻点数据重置为0,表示不需要消耗时间即可到达{int s;cin>>s;e[0][s]=0;vis[s]=0;}for(int i=0;i<=maxn;i++){vis[i]=e[0][i];dis.push(data(vis[i],i));}while(!dis.empty()){int v=dis.top().flag;dis.pop(); if(book[v]==1)//判断是否该点已经松弛过其他点continue;book[v]=1;for(int k=1;k<=maxn;k++)//dijkstra核心代码  松弛+将被松弛的点放入队列{if(e[v][k]<inf){if(vis[v]+e[v][k]<vis[k]){vis[k]=vis[v]+e[v][k];dis.push(data(vis[k],k));}} } }for(int i=0;i<d;i++)//维护到每个目的地距离的最小值{cin>>want[i];ans=min(ans,vis[want[i]]);}cout<<ans<<endl;}}


阅读全文
0 0
原创粉丝点击