n 为点数, m为边数
边权为正:朴素Dijkstra(n * n), 堆优化Dijstra算法(mlogn)。
边权为负:Bellman-Ford(n * m),spfa(平均o(m),最坏nm)。
用于稠密图。m 和 n * n 一个级别。
#include
/* ----------------------------------------
存储方式:邻接矩阵(二维数组)
s 已经确认最短路的点。
① dist[1] = 0, dist[i] = inf;
② for i : 0 ~ n
t <- 不在s 中的距离最近的点。
s <- t 用t 更新其他所有点的距离。
*///----------------------------------------
using namespace std;
const int N = 510;
int n , m;
int g[N][N];
int dist[N];
bool st[N];
int dijkstra()
{
memset(dist, 0x3f, sizeof dist);
dist[1] = 0;
for(int i = 0;i < n;i ++)
{
int t = -1;
for(int j = 1;j <= n;j ++)
if(!st[j] &&(t == -1 || dist[t] > dist[j]))
t = j;
st[t] = true;
for(int j = 1;j <= n;j ++)
dist[j] = min(dist[j], dist[t] + g[t][j]);
}
if(dist[n] == 0x3f3f3f3f)return -1;
return dist[n];
}
int main()
{
scanf("%d%d", &n, &m);
memset(g, 0x3f ,sizeof g);
while(m --)
{
int a, b , c;
scanf("%d%d%d",&a, &b, &c);
g[a][b] = min(g[a][b], c);
}
int t = dijkstra();
printf("%d\n", t);
return 0;
}
用于稀疏图。m 和 n 一个级别。
#include
/* ----------------------------------------
堆优化
存储方式:邻接表
s 已经确认最短路的点。
① dist[1] = 0, dist[i] = inf;
② for i : 0 ~ n
t <- 不在s 中的距离最近的点。
s <- t 用t 更新其他所有点的距离。
*///----------------------------------------
using namespace std;
typedef pair<int , int> PII;
const int N = 1000010;
int n , m;
int h[N], w[N], e[N], ne[N], idx;
int dist[N];
bool st[N];
void add(int a, int b, int c)
{
e[idx] = b, w[idx] = c , ne[idx] = h[a] , h[a] = idx ++;
}
int dijkstra()
{
memset(dist,0x3f,sizeof dist);
dist[1] = 0;
priority_queue<PII, vector<PII>,greater<PII> >heap;
heap.push({
0, 1});
while(heap.size())
{
auto t = heap.top();
heap.pop();
int ver = t.second ,distance = t.first;
if(st[ver]) continue;
else st[ver] = true;
for(int i = h[ver]; i != -1;i = ne[i])
{
int j = e[i];
if(dist[j] > distance + w[i])
{
dist[j] = distance + w[i];
heap.push({
dist[j], j});
}
}
}
if(dist[n] == 0x3f3f3f3f) return -1;
return dist[n];
}
int main()
{
scanf("%d%d", &n, &m);
memset(h, -1, sizeof h);
while(m --)
{
int a, b , c;
scanf("%d%d%d",&a, &b, &c);
add(a, b ,c);
}
int t = dijkstra();
printf("%d\n", t);
return 0;
}
#include
#include
#include
using namespace std;
const int N = 510, M = 10010;
int n , m , k;
int dist[N], backup[N];
struct Edge{
int a , b , w;
}edges[M];
int Bellman_Ford()
{
memset(dist, 0x3f , sizeof dist);
dist[1] = 0;
for(int i = 0;i < k;i ++)
{
memcpy(backup, dist, sizeof dist);
for(int j = 0;j < m;j ++)
{
int a = edges[j].a, b = edges[j].b, w = edges[j].w;
dist[b] = min(dist[b], backup[a] + w);
}
}
if(dist[n] >= 0x3f3f3f3f / 2) return -1;
return dist[n];
}
int main()
{
scanf("%d%d%d",&n,&m,&k);
for(int i = 0;i < m;i ++)
{
int a, b ,w;
scanf("%d%d%d", &a,&b,&w);
edges[i] = {
a, b, w};
}
int t = Bellman_Ford();
if(t == -1)puts("impossible");
else printf("%d\n", t);
return 0;
}
#include
/* ----------------------------------------
spfa
*///----------------------------------------
using namespace std;
typedef pair<int , int> PII;
const int N = 1000010;
int n , m;
int h[N], w[N], e[N], ne[N], idx;
int dist[N];
queue<int> q;
bool st[N];
void add(int a, int b, int c)
{
e[idx] = b, w[idx] = c , ne[idx] = h[a] , h[a] = idx ++;
}
int spfa()
{
memset(dist , 0x3f, sizeof dist);
dist[1] = 0;
q.push(1);
st[1] = true;
while(q.size())
{
int t = q.front();
q.pop();
st[t] = false;
for(int i = h[t]; i != -1;i = ne[i])
{
int j = e[i];
if(dist[j] > dist[t] + w[i])
{
dist[j] = dist[t] + w[i];
if(!st[j])
{
q.push(j);
st[j] = true;
}
}
}
}
if(dist[n] == 0x3f3f3f3f) return -1;
return dist[n];
}
int main()
{
scanf("%d%d", &n, &m);
memset(h, -1, sizeof h);
while(m --)
{
int a, b , c;
scanf("%d%d%d",&a, &b, &c);
add(a, b ,c);
}
int t = spfa();
if(t == -1)puts("impossible");
else printf("%d\n", t);
return 0;
}
Floyd(n * n * n)算法
#include
#include
#include
using namespace std;
const int N = 210, INF = 1e9;
int n , m , Q;
int d[N][N];
void floyd()
{
for(int k = 1;k <= n;k ++)
for(int i = 1;i <= n;i ++)
for(int j = 1;j <= n;j ++)
d[i][j] = min(d[i][j] , d[i][k] + d[k][j]);
}
int main()
{
scanf("%d%d%d", &n, &m, &Q);
for(int i = 1;i <= n;i ++)
for(int j = 1;j <= n;j ++)
if(i == j)d[i][j] = 0;
else d[i][j] = INF;
while(m --)
{
int a , b, w;
scanf("%d%d%d", &a , &b ,&w);
d[a][b] = min(d[a][b], w);
}
floyd();
while(Q --)
{
int l , r;
scanf("%d%d", &l, &r);
if(d[l][r] >= INF / 2)puts("impossible");
else printf("%d\n", d[l][r]);
}
return 0;
}
朴素版本Prim(n ^ n),堆优化(mlogn)
Kruskal(mlogm)
染色法(n + m), 匈牙利算法(nm, 实际运行时间远小于nm)