算法训练之最短路

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]});
          }
     } 
   }
}
发布了22 篇原创文章 · 获赞 2 · 访问量 2982

猜你喜欢

转载自blog.csdn.net/qq_40623603/article/details/105497409