欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

萌新の——迪杰特斯拉

程序员文章站 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)。
从起点开始,邻边进队,