最短路:Dijkstra
1算法流程
:我们要维护一个顶点集合C,满足对于所有集合C中的顶点x,我们都已经找到了起点S到x的最短路,此时dist(x)记录的就是我们最终最短路的长度
将C设置为空,经S的距离设置为0,其余顶点设置为无穷大(-1)
在每一轮中,将离起点最近的(dist最小,不能是无穷大)的还不在C中的顶点加入C,用这个点连出去的边通过松弛操作更新dist数组
当T没有新的点加入,算法结束
2Code:
时间复杂度On2+m)
struct Node{
int y,v;
Node(int _y,int _v){ y=_y;v=_v;};
};
vector<Node> edge[N+5];
int n,m,dist[N+5];
bool b[N+5];
int Dijkstra(int s,int ){
memset(b,fase,sizeof(b));
memset(dist,-1,sizeof(dist));
dist[s]=0;
while(true){
int x=-1;
for(int i=1;i<=n;i++){
if(!b[i]&&dist[i]!=-1)
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];
}
3 算法优化:
-我们可以采用一个堆(优先队列)来维护dist数组,算法复杂度可以提升到O((n+m)logn);
-优先队列的作用是替代每次迭代时找到离起点最近的点(可以用set集合替代)
struct Node{
int y,v;
Node(int _y,int _v){ y=_y;v=_v;};
};
vector<Node> edge[N+5];
set<pair<int,int>> q;//set底层是红黑树,有序的,先对pair->first进行排序,然后回pair->seconde进行排序
vector<Node> edge[N+5];
int n,m,dist[N+5];
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(make_pair(dist[i],i));
while(!q.empty()){
int x=q.begin()->second;
q.erase(q.begin());
if(x==t||dist[x]==-1) break;
for(auto i:edge[x]){
if(dist[x]+i.v<dist[i.y]){
q.erase(make_pair(dist[i.y],i.y));
dist[i.y]=dist[x]+i.v;
q.insert(make_pair(dist[i.y].i.y));
}
}
}
return dist[t];
}
//使用set 不能直接修改数据,要先erase在insert,因为set内部是红黑树实现,有序的
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll inf = 0x3f3f3f;
const ll maxn = 1e5 + 5;
struct Edge{
int y,v;
Edge(int _y,int _v){
y=_y;
v=_v;
}
};
vector<Edge> edge[200005];
int n,m,k;
int dist[maxn];
bool flag[maxn];
set<pair<int,int>> s;
int Dijkstra(int p,int q)
{
memset(dist,127,sizeof(dist));
memset(flag,false,sizeof(flag));
s.clear();
dist[p]=0;
for(int i=1;i<=n;i++) s.insert(make_pair(dist[i],i));
for(;!s.empty();)
{
int x=s.begin()->second;
s.erase(s.begin());
if(x==q||dist[x]>1<<30) break;
flag[x]=true;
for(auto it:edge[x])
{
if(it.v+dist[x]<dist[it.y])
{
s.erase(make_pair(dist[it.y],it.y));
dist[it.y]=it.v+dist[x];
s.insert(make_pair(dist[it.y],it.y));
}
}
}
if(dist[q]>1<<30)
return -1;
else
return dist[q];
}
void solve()
{
cin>>n>>m>>k;
for(int i=1;i<=m;i++)
{
int x,y,z;
cin>>x>>y>>z;
edge[x].push_back(Edge(y,z));
}
for(int i=1;i<=k;i++)
{ int x,y;
cin>>x>>y;
cout<<Dijkstra(x,y)<<'\n';
}
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
ll n = 1;
while (n--)
{
solve();
}
return 0;
}