萌新の——迪杰特斯拉
程序员文章站
2022-05-22 10:49:43
...
迪杰特斯拉
#include<iostream>
#include<queue>
using namespace std;
const int maxn = 1e5+10;
const int INF = 1e9;
struct edge{
int from,to,value; //起点,终点,权值
edge(int a,int b,int c){
from =a;
to= b;
value = c;
}
};
vector<edge> e[maxn]; //邻接表
int pre[maxn];
struct s_node{
int id,dis; // 结点,起点到id的最小距离
s_node(int a,int b){
id= a;
dis=b;
}
bool operator < (const s_node &a) const
{ return dis>a.dis;}
};
int n,m; //n点 m边
void dijkstra(int s){ // 求两点权值最小
bool done[maxn]; // 标记
int dis[maxn]; // s到i的最小距离
for(int i=0;i<=n;i++){
dis[i] = INF;
done[i] =false;
}
dis[s] = 0;
s_node u(s,0);
//u.id=s; u.dis =0;
priority_queue<s_node> Q;
Q.push(u);
while(!Q.empty()){
u = Q.top(); // u ....s_ndoe
Q.pop();
if(done[u.id]) continue;
done[u.id]=true;
for(int i=0;i<e[u.id].size();i++){
edge v=e[u.id][i]; //起点u.id ,邻接表
//cout<<v.from<<" "<<v.to<<" "<<v.value<<" ";
//cout<<dis[v.to]<<" "<<dis[v.from]<<" "<<v.value<<endl;
if(done[v.to]) continue;
if(dis[v.to]>dis[v.from]+v.value){ //优先队列 刷新
//cout<<"jindsa"<<v.to<<" "<<dis[v.to]<<endl;
dis[v.to] = dis[v.from] + v.value;
Q.push(s_node(v.to,dis[v.to]));
pre[v.to] = pre[v.from];
}
}
}
for(int i=1;i<=n;i++)
printf("i:%d dis:%d\n",i,dis[i]);
cout<<endl;
}
int main (){
scanf("%d %d",&n,&m);
while(m--){
int a,b,c;
scanf("%d %d %d",&a,&b,&c); //u->v 权值
e[a].push_back(edge(a,b,c)); //
//e[b].push_back(edge(b,a,c));
}
dijkstra(1);
return 0;
}
代码用优先队列和邻接表实现迪杰特斯拉算法。
优先队列: 从一个点出发,邻边寻找最小路径,主要用到的
思想: 已经知道3到8的权值为dis(3到8)40,在之前有一点9,
且dis(3到9)+dis(9到8)<dis(3到8) ,那么dis(3-8)刷新。
队列向后添加。
怎么才能很快的编出这样的代码呢?
画图理解。
其实就是广度搜索(BFS)。
从起点开始,邻边进队,
上一篇: hdu 1179
下一篇: 迪杰特斯拉算法部分优化