魔法效果——dijkstra+堆(邻接表存储)
dijkstra本身每次要for一遍,才能找出最小的节点,但用了堆之后,直接取出堆首就可以了。
但要注意的一点是,c++自带的stl里的priority_queue本身是先入大出的,而我们要求的是最小值,所以我们在push的时候是插入负数,这样就能保证是先入小出的了
代码如下:
各种定义:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<queue> #define MAXN 300000 using namespace std; int edge,n,m,u,a,b,c; int head[MAXN],to[MAXN],next[MAXN],w[MAXN]; int used[MAXN]; struct data { int d,num; friend bool operator<(const data &a,const data &b) { return a.d>b.d; } }dis[MAXN]; priority_queue<data>team; void build(int a,int b,int c) //建表 { edge++; next[edge]=head[a]; w[edge]=c; to[edge]=b; head[a]=edge; }
主函数
scanf("%d%d",&n,&m); for(int i=1;i<=m;i++) { scanf("%d%d%d",&a,&b,&c); build(a,b,c); } for(int i=1;i<=n;i++) { dis[i].d=0x7fffffff/3;
dis[i].num=i; //赋初始值 } //dijkstra+堆的主要代码
dis[1].d=0;//把它的边做的最小 team.push(dis[1]);//插入这个节点
while(!team.empty())//非空 { data t=team.top(); team.pop(); int u=t.num; if(used[u])continue; used[u]=1; for(int i=head[u];i;i=next[i]) { if(dis[to[i]].d>dis[u].d+w[i]) { dis[to[i]].d=dis[u].d+w[i]; team.push(dis[to[i]]); } } } if(dis[n].d!=0x7fffffff/3)cout<<dis[n].d; else cout<<-1;
神奇吧,我也觉得很神奇!
据说这样写可以把时间降低到比spfa还要快,好厉害!!!(果然是魔法操作)
我博客里有大量的从别的博客复制过来的代码,分析,以及理解,但我一律会在文章后面标记原博客大佬博客名,其中部分会加以连接。
绝无抄袭的意思,只是为了我在复习的时候找博客方便。
如有原作者对此有不满,请在博客留言,我一定会删除该博文。