这里讲两个算法:dijkstra和spfa。floyd就不说了复杂的太高达到o(n3),不过多源用它还是很好的。
先来spfa,这个算法可以说是很快了,但是是玄学算法没人能解释。o(ke),不过一般出题人都会卡它...
这边用的是队列,首先用数组dis记录起点到每个结点的最短路径,用邻接表来存储图,用vis数组记录当前节点是否在队列中,用队列来保存待优化的结点,优化时每次取出队首结点,并且用队首节点来对最短路径进行更新并进行松弛操作,若最短路需要更新且不在队列中,就加入队列,不断进行松弛操作,直至队列空为止。
spfa算法:
#include <bits/stdc++.h>
#define maxn 500005
#define inf 2147483647
using namespace std;
struct node
{
int next, to, w;
};
int n, m, s, cnt;
node a[maxn];
queue<int> q;
int dis[maxn], head[maxn];
bool vis[maxn];
void add(int u, int v, int w)
{
a[++cnt].to = v;
a[cnt].w = w;
a[cnt].next = head[u];
head[u] = cnt;
}
void spfa()
{
for (int i = 1; i <= n; i++)
{
dis[i] = inf;
}
q.push(s);
dis[s] = 0;
vis[s] = 1;
while (!q.empty())
{
int u = q.front();
q.pop();
vis[u] = 0;
for (int i = head[u]; i; i = a[i].next)
{
int v = a[i].to;
if (dis[v] > dis[u] + a[i].w)
{
dis[v] = dis[u] + a[i].w;
if (!vis[v])
{
vis[v] = 1;
q.push(v);
}
}
}
}
}
int main()
{
cin >> n >> m >> s;
int x, y, z;
for (int i = 1; i <= m; i++)
{
cin >> x >> y >> z;
add(x, y, z);
}
spfa();
for (int i = 1; i <= n; i++)
cout << dis[i] << " ";
return 0;
}
dijkstra算法:
dijkstra就是一个通用的算法了,一般都用它,它是基于贪心的策略,首先用数组dis记录起点到每个结点的最短路径,再用一个数组保存已经找到最短路径的点,然后,从dis数组选择最小值,则该值就是源点s到该值对应的顶点的最短路径,并且把该点记为已经找到最短路,此时完成一个顶点,再看这个点能否到达其它点(记为v),将dis[v]的值进行更新。复杂度为o(n2)。
我这边用的是前向星和优先队列(堆优化)
#include <bits/stdc++.h>
#define maxn 500005
#define inf 2147483647
using namespace std;
struct node
{
int to, w, next;
};
node a[maxn];
int head[maxn], n, m, s, cnt, dis[maxn];
bool vis[maxn];
typedef pair<int, int> P;
priority_queue<P, vector<P>, greater<P> > q;
void add(int u, int v, int w)
{
a[++cnt].to = v;
a[cnt].w = w;
a[cnt].next = head[u];
head[u] = cnt;
}
void dijkstra()
{
for (int i = 1; i <= n; i++)
dis[i] = inf;
dis[s] = 0;
q.push(make_pair(0, s));
while (!q.empty())
{
int u = q.top().second;
q.pop();
if (vis[u])
continue;
vis[u] = 1;
for (int i = head[u]; i; i = a[i].next)
{
int v = a[i].to;
if (!vis[v] && dis[v] > dis[u] + a[i].w)
{
dis[v] = dis[u] + a[i].w;
q.push(make_pair(dis[v], v));
}
}
}
}
int main()
{
cin >> n >> m >> s;
int x, y, z;
for (int i = 1; i <= m; i++)
{
cin >> x >> y >> z;
add(x, y, z);
}
dijkstra();
for (int i = 1; i <= n; i++)
cout << dis[i] << " ";
return 0;
}