目录
一、Floyd算法
Floyd是最短路里面最简单,也是最好理解的一个算法,其本身的含义就是寻求是否需要中间的一个过度点,其用到的三层for循坏。
1.时间复杂度:
o(n的三次方)。
2.Floyd的模板代码
void Floyd()
{
for(int k=1;k<=n;k++)//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]);
}
}
}
}
3.例题
http://acm.mangata.ltd/p/P1507
#include<bits/stdc++.h>
using namespace std;
const int INF = 0x3f3f3f3f;
const int N = 8e2+10;
int n,m,k;
int f[N][N];
void init()
{
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
f[i][j] = i==j?0:INF;
}
}
}
void Floyd()
{
for(int k=1;k<=n;k++)//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]);
}
}
}
}
int main()
{
cin>>n>>m>>k;
init();
while(m--)
{
int u,v,w;
cin>>u>>v>>w;
f[u][v] = min(f[u][v],w);
}
Floyd();
while(k--)
{
int x,y;
cin>>x>>y;
if(f[x][y]>INF/2)cout<<"impossible"<<endl;
else cout<<f[x][y]<<endl;
}
return 0;
}
二.bellman_ford算法
这也是一个比较暴力的算法,其也是通过松弛来进行操作,通过循环就能够解决,这个方法可以处理大部分的图。
1.时间复杂度
n*m。
2.算法模板
void bellman_ford(int s)//s表示初始序号;
{
for(int i=1;i<=n;i++) dis[i]=INF;
dis[s]=0;
for(int i = 1;i <=n; i++)
{
for(int j = 0;j < 2 * m; j++)
{
int v=E[j].v,u=E[j].u,w=E[j].w;
if(dis[v] > dis[u] + w)
dis[v] = dis[u] + w;
}
}
}
3.例题
http://acm.mangata.ltd/p/P1063
#include<bits/stdc++.h>
using namespace std;
const int INF = 0x3f3f3f3f;
const int N = 1e3+10;
int n,m;
struct ma{
int u,v,w;
};
int dis[N];
vector <ma> E;
void bellman_ford(int s)
{
for(int i=1;i<=n;i++) dis[i]=INF;
dis[s]=0;
for(int i = 1;i <=n; i++)
{
for(int j = 0;j < 2 * m; j++)
{
int v=E[j].v,u=E[j].u,w=E[j].w;
if(dis[v] > dis[u] + w)
dis[v] = dis[u] + w;
}
}
}
int main()
{
cin>>n>>m;
int t=m;
while(t--)
{
int u,v,w;
cin>>u>>v>>w;
E.push_back({u,v,w});//因为是无向图;
E.push_back({v,u,w});
}
int ans=INF;
for(int i=1;i<=n;i++)
{
int cnt=0;
bellman_ford(i);//把每个起点都寻求一遍;
for(int j=1;j<=n;j++)
{
cnt+=dis[j];
}
ans=min(ans,cnt);
}
cout<<ans<<endl;
return 0;
}
三.SPFA
这是bellman_ford算法的队列优化,其思维和bellman_ford差不多
1.模板代码:
void SPFA(int s)
{
for(int i=0;i <= n;++i) dis[i]=INF,vis[i]=false;
dis[s] = 0;vis[s] = true;
queue<int> q;
q.push(s);
while(!q.empty())
{
int t = q.front();
q.pop();
vis[t]= false;
for(int i =0,l = E[t].size();i<l;++i)
{
int j =E[t][i].first,w = E[t][i].second;
if(dis[j]>dis[t]+w)
{
dis[j] = dis[t]+w;
if(!vis[j]) q.push(j),vis[j] = true;
}
}
}
}
2.例题
同bellman_ford.
#include<bits/stdc++.h>
using namespace std;
#define PII pair<int,int>
const int INF = 0x3f3f3f3f;
const int N = 1e3+10;
int n,m;
int dis[N];
bool vis[N];
vector <PII> E[N];
void SPFA(int s)
{
for(int i=0;i <= n;++i) dis[i]=INF,vis[i]=false;
dis[s] = 0;vis[s] = true;
queue<int> q;
q.push(s);
while(!q.empty())
{
int t = q.front();
q.pop();
vis[t]= false;
for(int i =0,l = E[t].size();i<l;++i)
{
int j =E[t][i].first,w = E[t][i].second;
if(dis[j]>dis[t]+w)
{
dis[j] = dis[t]+w;
if(!vis[j]) q.push(j),vis[j] = true;
}
}
}
}
int main()
{
cin>>n>>m;
int t=m;
// while(t--)
// {
// int u,v,w;
// cin>>u>>v>>w;
// E.push_back({u,v,w});//因为是无向图;
// E.push_back({v,u,w});
// }
while(t--)
{
int u,v,w;
cin>>u>>v>>w;
E[u].push_back({v,w});
E[v].push_back({u,w});
}
int ans=INF;
for(int i=1;i<=n;i++)
{
int cnt=0;
//bellman_ford(i);//把每个起点都寻求一遍;
SPFA(i);
for(int j=1;j<=n;j++)
{
cnt+=dis[j];
}
ans=min(ans,cnt);
// cout<<ans;
}
cout<<ans<<endl;
return 0;
}