floyed
多源最短路 通过枚举中转点来更新点到点直接的最短路距离 时间复杂度为n3 通常用来解解决点比较少的最短路问题 实际上这是个动态规划的简单应用。
for(int k=1;k<=n;i++)
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
dp[i][j]=max(dp[i][j],dp[i][k]+dp[k][j]);
Bellman-ford
单源最短路
经过|V|-1轮松弛,要是仍得不到最短路,那么说明存在负环。
for(int i=1;i<n;i++)dis[i]=INF; dis[0]=0;
for(int k=0;k<n-1;k++)
for(int i=0;i<m;i++)
{
int x=u[i],y=v[i];
if(dis[x]<INF)dis[y]=min(dis[y],dis[x]+w[i]);
}
dijstra
单源最短路。不能用于负权边的图使用
主要思想就是从最短距离找到已确定的顶点进行松弛。
每次找出dis[i]最小的顶点然后从它出发进行松弛即可,使用堆优化时间复杂度可以达到E+Vlogv
没有堆优化时间复杂度为n2
struct Edge{int to,val;Edge(int e,int v):to(e),val(v}{} };
vector<Edge>g[N]; bool vis[N];int dis[N];
void dij(int st)//表示st这点到所有点的最短距离
{ memset(dis,0x3f,sizeof(dis));
dis[st]=0; memset(vis,0,sizeof(vis));
for(int i=1;i<=n;i++)
{ int Min=inf;
for(int j=1;j<=n;j++)
if(!vis[j]&&(Min==inf||dis[j]<dis[Min]))Min=j;
if(Min=inf)return ;
vis[Min]=true;
for(auto it:g[Min])
{
if(!vis[it.to])
dis[it.to]=min(dis[it.to],dis[Min]+it.val);
}
}
}
堆优化的写法使用联试前向星来存图;
int head[n];int tot;
struct edge{int to,val,nxt;}ed[N<<1];//无向边通常都是开两倍存储
void add(int u,int v,int w)
{ ed[++tot].to=v;ed[tot].val=w;ed[tot].nxt=head[u];head[u]=tot;
}
struct node{int id,dis;bool operator<(const node&a)const
{return dis>a.dis;}} bool vis[N];int dis[N];
void dij(int st)
{
memset(vis,false,sizeof(vis));
memset(dis,inf,sizeof(dis)); dis[st]=0;
priority_queue<node>q;
q.push(node {st,0});
while(!q.empty())
{
int x=q.top().id;q.pop();
if(vis[x]) continue; vis[x]=true;
for(int i=head[x];i;i=ed[i].nxt)
{
int end=ed[i].to;
if(dis[end]>dis[x]+ed[i].val)
{dis[end]=dis[x]+ed[i].val;
q.push(node{end,dis[end]});
}
}
}
}