bellman ford不常用下面有它的优化spfa

for (int i = 0; i < n; i++) {
    for (int j = 0; j < m; j++) {
        d[v[i]] = min(d[v[i]], d[u[i]] + w[i]);
    }
}

dijkstra

d[s] = 0;//自己到自己0
for (int i = 0; i < n; i++) {
    int t = -1;
    for (int j = 0; j < n; j++) {
        if (!v[j]) {
            if (t == -1 || d[j] < d[t]) {
                t = j;
            }
        }
    }
    v[t] = 1;
    for (each edge e of t) {
        relax(e);//松弛
    }
}

floyd

for (int k = 0; k < n; k++) {
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            f[i][j] = min(f[i][j], f[i][k]+f[k][j])
        }
    }
}

spfa(洛谷大佬代码)

void spfa()
{
  queue<int> q; //spfa用队列,这里用了stl的标准队列
  for(int i=1; i<=n; i++) 
  {
    dis[i]=inf; //带权图初始化
    vis[i]=0; //记录点i是否在队列中,同dijkstra算法中的visited数组
  }
  q.push(s); dis[s]=0; vis[s]=1; //第一个顶点入队,进行标记
  while(!q.empty())
  {
    int u=q.front(); //取出队首
    q.pop(); vis[u]=0; //出队标记
    for(int i=head[u]; i; i=edge[i].next) //邻接表遍历,不多解释了(也可用vector代替)
    {
      int v=edge[i].to; 
      if(dis[v]>dis[u]+edge[i].dis) //如果有最短路就更改
      {
        dis[v]=dis[u]+edge[i].dis;
        if(vis[v]==0) //未入队则入队
        {
          vis[v]=1; //标记入队
          q.push(v);
        }
      }
    }
  }
}

例 : luogu p3371 预备知识: 链式前向星

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e4 + 5;
const int maxm = 5e5 + 5;
const ll inf = 2147483647;
struct edge{
    int next,to,w;
}e[maxm];
int head[maxn], cnt, n, m, s, vis[maxn], dis[maxn];//head初始化为0
priority_queue<int, vector< pair<int, int> >, greater< pair<int, int> > >q;//最小堆,dijkstra找最短距离的

inline void add(int u, int v, int w){//链式向前星
    e[cnt].w = w;//存权重
    e[cnt].to = v;
    e[cnt].next = head[u];
    head[u] = cnt++;
}

void dijkstra(){
    q.push(make_pair(0, s));//起点s进去
    while(!q.empty()){//空了就全搞好了
        int now = q.top().second;//当前点
        q.pop();//没用了弹出
        if(!vis[now]){//要没标记
            vis[now] = 1;//标记了
            for(int i = head[now]; i; i = e[i].next){//把与now有联系的都循环,i = 0就没了,head初始化就是0
                int v = e[i].to;
                if(dis[v] > dis[now] + e[i].w){
                    dis[v] = dis[now] + e[i].w;
                    q.push(make_pair(dis[v], v));//发现它变小了就推进去
                }
            }
        }
    }
}

int main(){
    //ios_base::sync_with_stdio(0);
    //cin.tie(); cout.tie();
    cin>>n>>m>>s;
    int x, y, z;
    for(int i = 1; i <= m; i++){
        cin>>x>>y>>z;
        add(x, y, z);//链式向前星
    }
    for(int i = 1; i <= n; i++)
        dis[i] = inf;//初始化
    dis[s] = 0;//自己
    dijkstra();
    for(int i = 1; i <= n; i++){
        cout<<dis[i]<<' ';
    }
    return 0;
}

例 :luogu p1821 正反两次最短路(大佬代码)

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<vector>
using namespace std;
struct edge
{
    int u,v;    
};

vector<edge> g[3][1001];//动态数组存边

queue<int> q;//队列(stl大法好)

int n,m,f[3][1001],l,ans;
bool vis[1001];

void spfa(int k)//k=1时正向图,k=2时反向图
{
    memset(vis,0,sizeof(vis));//初始化false
    vis[l]=true;
    f[k][l]=0;
    q.push(l);
    while(!q.empty())
    {
        int news=q.front();
        q.pop();
        vis[news]=false;
        for(int i=0;i<g[k][news].size();i++)
        {
            int v=g[k][news][i].v,u=g[k][news][i].u;
            if(f[k][v]>f[k][news]+u)
            {
                f[k][v]=f[k][news]+u;
                if(!vis[v])
                {
                    vis[v]=true;
                    q.push(v);
                }
            }
        }
    }
}

int main()
{
    scanf("%d%d%d",&n,&m,&l);
    memset(f,0x3f3f3f,sizeof(f));
    for(int a=1;a<=m;a++)
    {
        int x,y,z;
        scanf("%d%d%d",&x,&y,&z);
        edge cmp;
        cmp.v=y;
        cmp.u=z;
        g[1][x].push_back(cmp);//正向建图
        cmp.v=x;
        g[2][y].push_back(cmp);//反向建图
    }
    spfa(1);//跑正向图
    spfa(2);//跑反向图
    for(int a=1;a<=n;a++)
    {
        if(a==l)
        {
            continue;
        }
        ans=max(f[1][a]+f[2][a],ans);//找最长的
    }
    printf("%dn",ans);
    return 0;
}

正向建就是求各点到终点最短路,反向建求终点到各点最短路

分类: 未分类

0 条评论

发表回复

Avatar placeholder

您的邮箱地址不会被公开。 必填项已用 * 标注