最短路 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