单源一般都是对边操作,多源一般对点操作
Bellman
适用于
- 单源最短路
- 复杂度要求不高或可能有负边
复杂度O(V E)
n是边的数量,k是顶点数量
直接用edge来储存关系,因为每次都是将所有的边拿来更新一次
/*
* @Description:
* @Autor: Kadia
* @Date: 2020-05-18 12:13:37
* @LastEditors: Kadia
* @connect: vx:ccz1354 qq:544692713
* @LastEditTime: 2020-06-15 23:22:35
*/
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
struct edge
{
int from;
int to;
int cost;
}city[50];
int d[50];
int main()
{
int n,k;
cin >> n >> k;
int a,b,x;
for (int i = 1; i <= n; i++)
{
cin >> city[i].from >> city[i].to >> city[i].cost;
}
for(int i=1;i<=n;i++)
d[i]=INF;
d[1]=0;
for(int i=1;i<k;i++)
{
for(int j=1;j<=n;j++)
{
d[city[j].to]=min(d[city[j].to],d[city[j].from]+city[j].cost);
}
}
cin >> x;
cout << d[x] << endl ;
return 0;
}
spaf-改良版Bellman
用一个queue记录上次更新过的点,没有更新多的点就不用重复去松弛了
/*
* @Description:
* @Autor: Kadia
* @Date: 2020-07-17 11:28:37
* @LastEditors: Kadia
* @Connect: vx:ccz1354 qq:544692713
* @LastEditTime: 2020-07-17 11:51:52
*/
//spaf
#include <bits/stdc++.h>
#define inf 2147483647
using namespace std;
struct _edge
{
int from;
int to;
int cost;
};
int vis[10005];
int len[10005];
int main()
{
ios::sync_with_stdio(false);
int n,m,s;
cin >> n >> m >> s;
vector<_edge>save[10005];
int f,t,c;
for(int i=1;i<=m;i++)
{
cin >> f >> t >> c;
save[f].push_back(_edge{f,t,c});
}
queue<int>que;
for(int i=1;i<=n;i++)
len[i]=inf;
len[s]=0;
que.push(s);
vis[s]++;
while(que.size())
{
int v=que.front();
que.pop();
vis[v]--;
for(int i=0;i<(int)save[v].size();i++)
{
_edge e=save[v][i];
if(len[e.to]>len[v]+e.cost)
{
len[e.to]=len[v]+e.cost;
if(!vis[e.to])
{
vis[e.to]++;
que.push(e.to);
}
}
}
}
for(int i=1;i<=n;i++)
{
if(i==1)
cout << len[i] ;
else
cout << " " << len[i] ;
}
cout << endl ;
return 0;
}
Dijkstra
适用于
- 单源最短路
- 没有负边的情况
复杂度O((E+N)logN)
n是边的数量
用存edge的vector的G[X]来表示x出发的路,因为与第一种不同,不需要每一个边都遍历,但要用一个中间点出发的点和费用,所以用vector来储存
/*
* @Description:
* @Autor: Kadia
* @Date: 2020-05-18 12:13:37
* @LastEditors: Kadia
* @connect: vx:ccz1354 qq:544692713
* @LastEditTime: 2020-06-15 23:26:04
*/
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
struct edge
{
int from;
int to;
int cost;
} ;
int d[50];
vector<edge> G[50];
int main()
{
int n;
cin >> n ;
int a,b,x;
for (int i = 1; i <= n; i++)
{
cin >> a >> b >> x;
G[a].push_back(edge{a,b,x});
}
for(int i=1;i<=n;i++)
d[i]=INF;
d[1]=0;
priority_queue<pair<int,int>,vector<pair<int,int> >, greater<pair<int,int> > >que;
que.push(pair<int,int>(0,1));
while(que.size())
{
pair<int,int>tmp=que.top();
que.pop();
int v=tmp.second;
if(d[v]!=tmp.first)
continue;
for(int i=0;i<G[v].size();i++)
{
edge e=G[v][i];
if(d[e.to]>d[v]+e.cost)
{
d[e.to]=d[v]+e.cost;
que.push(pair<int,int>(d[e.to],e.to));
}
}
}
cin >> x;
cout << d[x] << endl ;
return 0;
}
Warshall
适用于
- 求多源最短路
复杂度O(V V V)
/*
* @Description:
* @Autor: Kadia
* @Date: 2020-06-15 15:03:12
* @LastEditors: Kadia
* @connect: vx:ccz1354 qq:544692713
* @LastEditTime: 2020-06-15 15:17:20
*/
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
struct _node
{
int x;
int y;
}node[105];
double ma[105][105];
int main()
{
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
if(i==j)
ma[i][j]=0;
else
ma[i][j]=INF;
}
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
for(int k=1;k<=n;k++)
{
ma[j][k]=min(ma[j][k],ma[j][i]+ma[i][k]);
}
}
}
return 0;
}