最短路
1.floyed多源最短路
稳定的\(O(n^3)\)预处理,\(O(1)\)查询。
加深理解:floyed的最外层枚举k时,k是任意枚举的,也就是说k可以用来维护其他操作,如赋给每个点一个点权,sort一下,再跑floyed,此时的k就可以作为走过路径的点权最大值,可与最短路一起维护。
点击查看代码
for(int k=1;k<=n;k++)
{
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
}
}
}
2.dij单源最短路
可分为朴素版和堆优化版,朴素版的复杂度为\(O(n^2)\),而堆优化版则为\(mlogn\),做题的时候要做好取舍,总有一些丧心病狂的出题者会卡堆优化。
一般来说是dis[i][j],但具体题可以把最短路当做DP来做,我们就可以给它加状态来维护更多信息。
从教练那里直接搬过来了
朴素版
点击查看代码
//初始化
#include <bits/stdc++.h>
using namespace std;
const int maxn = 510;
const int inf = 0x7f7f7f7f;
int n = 0, m = 0;
int g[maxn][maxn] = {}; //朴素版的dijkstra算法多用与稠密图,因此用邻接矩阵存图
int dis[maxn] = {}; //存储1号点到每个点的最短距离
int vis[maxn] = {}; //存储每个点的最短路是否已经确定
//求1号点到n号点的最短路
void dij()
{
memset(dis, 0x3f, sizeof(dis));
dis[1] = 0;
for(int i=1; i<n; i++)
{
int t = -1;
//在还未确定最短路的点中,寻找距离最小的点
for(int j=1; j<=n; j++)
{
if(!vis[j] && (t==-1 || dis[t]>dis[j])) t = j;
}
//用t更新其他点的距离
for(int j=1; j<=n; j++)
{
dis[j] = min(dis[j], dis[t] + g[t][j]);
}
vis[t] = true;
}
}
int main()
{
int x = 0, y = 0, z = 0;
scanf("%d%d", &n, &m);
memset(g, 0x3f, sizeof(g));
for(int i=1; i<=n; i++) g[i][i] = 0;
for(int i=1; i<=m; i++)
{
scanf("%d%d%d", &x, &y, &z);
g[x][y] = min(g[x][y], z);
}
dij();
if(dis[n] == 0x3f3f3f3f) printf("-1");
else printf("%d", dis[n]);
return 0;
}
点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int N=105;
const int M=5000;
int h[N],to[M],nxt[M],w[M],tot;
void add(int x,int y,int dt)
{
tot++;
w[tot]=dt;
to[tot]=y;
nxt[tot]=h[x];
h[x]=tot;
}
int dis[N];
bool vis[N];
priority_queue< pair<int,int> >q;
void dij()
{
memset(dis,0x3f,sizeof(dis));
memset(vis,0,sizeof(vis));
dis[1]=0;
q.push(make_pair(-dis[1],1));
while(!q.empty())
{
int x=q.top().second;
q.pop();
vis[x]=1;
for(int i=h[x];i;i=nxt[i])
{
int y=to[i];
if(dis[y]>dis[x]+w[i])
{
dis[y]=dis[x]+w[i];
if(!vis[y])
{
q.push(make_pair(-dis[y],y));
}
}
}
}
}
int main()
{
int n,m;
cin>>n>>m;
for(int i=1;i<=m;i++)
{
int x,y,dt;
cin>>x>>y>>dt;
add(x,y,dt);
add(y,x,dt);
}
dij();
int ans=0;
for(int i=1;i<=n;i++)
{
if(dis[i]==0x3f)
{
cout<<-1;
exit(0);
}
else
{
ans=max(ans,dis[i]);
}
}
cout<<ans;
}
3.spfa
spfa相比于dij的优点是可以判负环,可以跑最长路
没什么好说的,上板子
点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int N=2600;
const int M=15000;
int n,m;
int h[N],to[M],nxt[M],w[M],cnt;
void add(int x,int y,int dt)
{
cnt++;
w[cnt]=dt;
to[cnt]=y;
nxt[cnt]=h[x];
h[x]=cnt;
}
int dis[N],vis[N];
queue<int>q;
void spfa(int x)
{
memset(dis,0x3f,sizeof(dis));
memset(vis,0,sizeof(vis));
dis[x]=0;
q.push(x);
vis[x]=1;
while(!q.empty())
{
x=q.front();
vis[x]=0;
q.pop();
for(int i=h[x];i;i=nxt[i])
{
int y=to[i];
if(dis[y]>dis[x]+w[i])
{
dis[y]=dis[x]+w[i];
if(!vis[y])
{
q.push(y);
}
}
}
}
}
int main()
{
int n,m,ts,te;
cin>>n>>m>>ts>>te;
for(int i=1;i<=m;i++)
{
int x,y,dt;
cin>>x>>y>>dt;
add(x,y,dt);
add(y,x,dt);
}
spfa(ts);
cout<<dis[te];
}