算法笔记:图论单源最短路
求解所有两点间的最短路的问题叫做任意任意两点间的最短路问题。
Floyed-Warshall算法
类似dp思想的一种最短路算法
时间复杂度
\(O(n^{3})\)
处理限制
-
可以处理边权为负的情况
-
可以判断图中是否有负圈
-
时间复杂度过高
代码
//#define fre yes
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 256+10;
int d[maxn][maxn];
int n,m,t;
template<typename T>inline void read(T&x)
{
x = 0;char c;int lenp = 1;
do { c = getchar();if(c == '-') lenp = -1; } while(!isdigit(c));
do { x = x * 10 + c - '0';c = getchar(); } while(isdigit(c));
x *= lenp;
}
void floyd(int x)
{
for (int k=1;k<=x;k++)
{
for (int i=1;i<=x;i++)
{
for (int j=1;j<=x;j++)
{
d[i][j] = min(d[i][j],d[i][k]+d[k][j]);
} } }
}
int main()
{
memset(d,0x3f3f3f3f,sizeof(d));
read(n);read(m);read(t);
for (int i=1;i<=m;i++)
{
int x,y,z;
read(x);read(y);read(z);
d[x][y] = z;
} floyd(n);
for (int i=1;i<=n;i++) { if(t == i) { printf("0 ");continue; }printf("%d ",d[t][i]); }
return 0;
}
####Shortest Path Faster Algorithm (Spfa)算法 最短路径最快的算法(开玩笑)
类似广度优先搜索
时间复杂度
\(O(VE)\)
V:顶点数
E:边数
处理限制
-
可以处理边权为负的情况
-
可以判断图中是否有负圈
-
时间复杂度低,但容易被卡
代码
//#define fre yes
#include <queue>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 256+10;
int head[maxn];
int edge[maxn];
int ver[maxn];
int to[maxn];
int inq[maxn];
int d[maxn];
int n,m,t,tot;
template<typename T>inline void read(T&x)
{
x = 0;char c;int lenp = 1;
do { c = getchar();if(c == '-') lenp = -1; } while(!isdigit(c));
do { x = x * 10 + c - '0';c = getchar(); } while(isdigit(c));
x *= lenp;
}
void addedge(int x,int y,int z)
{
edge[tot] = z;
ver[tot] = y;
to[tot] = head[x];
head[x] = tot++;
}
void spfa(int x)
{
queue<int> q;
q.push(x);
d[x] = 0; inq[x] = 1;
while(!q.empty())
{
int now = q.front();q.pop();
for (int i=head[now];~i;i=to[i])
{
int v = ver[i];
if(d[v] > d[now] + edge[i])
{
d[v] = d[now] + edge[i];
if(inq[v] == 1) continue;
inq[v] = 1;
q.push(v);
}
}
}
}
int main()
{
memset(d,0x3f3f3f3f,sizeof(d));
memset(head,-1,sizeof(head));
read(n);read(m);read(t);
for (int i=1;i<=m;i++)
{
int x,y,z;
read(x);read(y);read(z);
addedge(x,y,z);
} spfa(t);
for (int i=1;i<=n;i++) printf("%d ",d[i]);
return 0;
}
####Dijkstra单源最短路算法
类似广度优先搜索
时间复杂度
如果Spfa是\(O(V^{2})\)
那么Dij就是\(O(Vlog_{E})\)
处理限制
-
不能处理负权的情况
-
速度比Spfa要快点
-
考试一般不卡
代码
//#define fre yes
#include <queue>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 256+10;
int head[maxn];
int edge[maxn];
int ver[maxn];
int to[maxn];
int d[maxn];
int n,m,t,tot;
template<typename T>inline void read(T&x)
{
x = 0;char c;int lenp = 1;
do { c = getchar();if(c == '-') lenp = -1; } while(!isdigit(c));
do { x = x * 10 + c - '0';c = getchar(); } while(isdigit(c));
x *= lenp;
}
void addedge(int x,int y,int z)
{
edge[tot] = z;
ver[tot] = y;
to[tot] = head[x];
head[x] = tot++;
}
void Dijkstra(int x)
{
priority_queue<pair<int,int> > q;
d[x] = 0;
q.push(make_pair(-d[x],x));
while(!q.empty())
{
int now = q.top().second;q.pop();
for (int i=head[now];~i;i=to[i])
{
int v = ver[i];
if(d[v] > d[now] + edge[i])
{
d[v] = d[now] + edge[i];
q.push(make_pair(-d[v],v));
}
}
}
}
int main()
{
memset(d,0x3f3f3f3f,sizeof(d));
memset(head,-1,sizeof(head));
read(n);read(m);read(t);
for (int i=1;i<=m;i++)
{
int x,y,z;
read(x);read(y);read(z);
addedge(x,y,z);
} Dijkstra(t);
for (int i=1;i<=n;i++) printf("%d ",d[i]);
return 0;
}