最短路算法
Floyd
说实话我真的不知道要不要加e了,就这样吧- 最简单的一种,三层循环结束,超级好记
- 当然,时间复杂度为O(N^3),建议n不超过200
设f[x][y]为x到y的最短路径的长度.
注:初始化 x,y有边相连f[x][y]=w[x][y],否则f[x][y]=0x3fffffff.
(也就是尽量大,不是0x7fffffff保证int不爆.)
for(int k=1;k<=n;k++)
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
f[i][j]=min(f[i][j],f[i][k]+f[k][j]);
- 它的大体思想是以k作为中转站,逐步更新。
- 注意k的循环要在最外层,保证不会漏点。
Dijkastra
- 计算某一点到其他点的最短路径,时间复杂度O(N^2)。
- 注意Dijkastra不能处理负边权。
- 大致流程为
初始化——找顶点——标记,更新
设起点为s,f[x]表示s到x的最短距离,用bool类型的flag数组标记是否已确定(即书上的“染色”).
for(int i=1;i<=n;i++)
f[i]=w[s][i];
f[s]=0,flag[s]=1;
for(int i=1;i<=n;i++){
int m=0x3fffffff,k;
for(int j=1;j<=n;j++)
if(!flag[j]&&f[j]<m)
m=f[j],k=j;
flag[k]=1;
for(int j=1;j<=n;j++)
if(!flag[j]&&f[k]+w[k][j]<f[j])
f[j]=f[k]+w[k][j];
}
SPFA
- SPFA和广搜有一点点像,区别就在于SPFA中每个点可以重复入队,但广搜不能。
设f[x]记录从s到x的最短距离,bool类数组flag记录该点是否在队列中.
queue<int> q;
for(int i=1;i<=n;i++)
f[i]=w[s][i];
q.push(s);flag[s]=1;
while(!q.empty()){
int x=q.front();q.pop();
flag[x]=0;
for 枚举与x相连的所有点i
if(f[i]>f[x]+w[i][x]){
f[i]=f[x]+w[i][x];
if(!flag[i]){
q.push(i);
flag[i]=1;
}
}
}
数据结构
链式前向星
int n,m,k;
int h[maxn]
struct node{
int w,to,next;
}f[maxn];
void add(int u,int v,int w){
k++;
f[k].to=v,f[k].w=w,f[k].next=h[u];
h[u]=k;
}
void init(){
for(int i=1;i<=n;i++)
h[i]=-1;
k=0;
}
void paint(){
for(int i=1;i<=n;i++){
for(int j=h[i];j!=-1;j=f[j].next)
cout<<i<<" "<<f[i].to<<" "<<f[i].w<<endl;
cout<<endl;
}
}
邻接表
- 结构如其名,用表存储点与点的距离,例如以上的Floyd就采用了邻接表。(希望小蒟蒻没写错)
- 这个模块就是来凑数的,没什么好说的。
- 主要是有点排版强迫症,把链式前向星和其他的排一起怪怪的。
完成撒花!
- 欧耶!我写完了!!!
- 历时一周的大作(并没有)
- 感想:拖延症真可怕
但我下次还敢拖 (此作者已被拉走(不要拖延啊这是教训)(bushi))- 总之,最后皮一下真的很开心
- FIN.