最短路 2

二.Dijkstra 这个基本上是用来跑边权为非负的图 ,算法复杂度O(n^2+m)
这个算法的思路是这样的:
先确定起点标记为0 然后从起点去看起点所连出去的边,找出边权最小的,再由他去遍历之后点然后继续去更新边权 再取最小 ,可以知道前面已经被访问的点不可能被后面的点再次更新!
一个贪心的基本思想!
然后每次跑一个o(n) 的取点 一共遍历n个点 一共遍历m条边

struct node{
	int y,v;
	node(int _y,int _v)// 这是一个构造函数!! 若有构造函数则不能在此定义中再定义变量!!
	{
		y=_y;
		v=_v;
	}
};
vector<node> edge[N+1];  // 记每个点所连出去的边!!   
int n,m,dist[N+1];      //  记最终最短路的长度!!
bool b[N+1];  //记访问过的数组!!
int dijkstra(int s,int t)
{
	memset(b,false,sizeof(b));
	memset(dist,127,sizeof(dist));  //赋值为无穷大
	dist[s]=0;
	while(1)
	{
		int x=-1;
		for(i=1;i<=n;i++)
		{
			if(!b[i]&&dist[i]<1<<30)//之前没被访问过!!且之前被更新过了也就是在更新点的一个集合中了!!
			if(x==-1||dist[i]<dist[x])// 这个条件要求的是找到没访问过的点中目前最小的  一个贪心的思路!
			x=i;
		}
		if(x==t||x==-1)
		break;
		b[x]=true;
		for(auto i:edge[x])
		dist[i.y]=min(dist[i.y],dist[x]+i.v);
	}
	return dist[t];
}

然后就是一个set优化 去优化找点! 主要是 但是点的修改是一个log n 的复杂度的所有最后导致时间复杂度是一个O((n+m)logn)

struct node{
   int y,v;
   node(int a,int b)
   {
   	y=a,v=b;
   }
};
set<pair<int,int>>q;
vector<node> edge[N+1];
int n,m,dist[N+1];
int dijkstra(int s,int t )
{
   memset(dist,127,sizeof(dist));  
   dist[s]=0;
   q.clear();
   for(int i=1;i<=n;i++)
   	q.insert({dist[i],i});  
   while(!q.empty())
   {
   	int y=q.begin()->second;  
   	q.erase(q.begin());
   	if(x==t||dist[x]>1<<30)
   		break;
   	for(auto i:edge[x])
   	{
   		if(dist[x]+i.v<dist[i.y])
   		{
   			q.erase({dist[i.y],i..y});
               //这样去改变点!因为在stl中set不能直接改变在那个集合中 
   	//故要通过堆集合中的点进行删除  修改后再添加回去才可!
                               dist[i.y]=dist[x]+i.v;    
   			q.insert({dist[i.y],i.y});//
   		}
   	}
   }
   return dist[t];
}
```w
posted @ 2023-03-26 22:07  _Lance  阅读(40)  评论(0编辑  收藏  举报