Floyd算法
主要思想(dp):以每个点作为中转点,其他任意俩点只经过此地的距离状态转移
主要代码:
for(k=1;k<=n;k++)
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
if(e[i][j]>e[i][k]+e[k][j])
e[i][j]=e[i][k]+e[k][j];
时间复杂度是O(N3)
不能解决带有“负权回路”(或者叫“负权环”)的图
P1119 灾后重建 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
dijkstra算法(优先)
主要思想(贪心):
Dijkstra是基于一种贪心的策略,首先用数组dis记录起点到每个结点的最短路径,再用一个数组保存已经找到最短路径的点
然后,从dis数组选择最小值,则该值就是源点s到该值对应的顶点的最短路径,并且把该点记为已经找到最短路
此时完成一个顶点,再看这个点能否到达其它点(记为v),将dis[v]的值进行更新
主要代码:
int tt,n,m,s,dis[100005],vis[100005];
vector<pair<int,int> >vt[100005];
priority_queue<pair<int,int>,vector<pair<int,int> >,greater<pair<int,int> > >q;
void solve(){
cin>>n>>m>>s;int u,v,w;memset(dis,0x7f,sizeof(dis));
for(int i=1;i<=m;i++){
cin>>u>>v>>w;
vt[u].push_back({v,w});
}
q.push({0,s});dis[s]=0;
while(!q.empty()){
int u=q.top().second;q.pop();
if(vis[u])continue;
for(auto it:vt[u]){
if(it.second+dis[u]<dis[it.first]){
dis[it.first]=it.second+dis[u];q.push({dis[it.first],it.first});
}
}
vis[u]=1;
}
for(int i=1;i<=n;i++)cout<<dis[i]<<' ';
}
时间复杂度:O(N2)
P4779 【模板】单源最短路径(标准版) - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
SPFA算法
主要思想(STL队列):
用队列来保存待优化的结点(类似于BFS),优化时每次取出队首结点,并且对每个邻接点最短路径进行更新,如果改点不在当前的队列中,就将改点加入队列
主要代码:
q.push(s);
dis[s]=0; //将起点的值负为0
while(!q.empty())
{
u=q.front();
q.pop();
vis[u]=0;
for(int i=head[u];i;i=h[i].next)
{
v=h[i].to;
if(dis[v]>dis[u]+h[i].w)
{
dis[v]=dis[u]+h[i].w;
if(!vis[v])
{
vis[v]=1;
q.push(v);
}
}
}
}
}
时间复杂度:O(nm)