最短路问题

一:Dijkstra(适用于无向图,但不适于有负边权的图)

1.朴素dijkstra

查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1000;
bool sign[N];
int g[N][N];
int dis[N];
int n,m;
int djs()
{
    for(int i=0;i<=n;i++)dis[i]=LLONG_MAX/2;
    dis[1]=0;
    for(int i=0;i<n;i++)
    {
        int t=-1;
        for(int j=1;j<=n;j++)
            if(!sign[j]&&(t==-1||dis[t]>dis[j]))t=j;
        sign[t]=1;
        for(int j=1;j<=n;j++)
        {
            dis[j]=min(dis[j],dis[t]+g[t][j]);
        }
    }
    if(dis[n]==LLONG_MAX/2)return -1;
    return dis[n];
}
signed main()
{
    memset(g,0x3f,sizeof g);
    cin>>n>>m;
    for(int i=0;i<m;i++)
    {
        int a,b,c;
        cin>>a>>b>>c;
        g[a][b]=min(g[a][b],c);
    }
    cout<<djs();
    return 0;
}

2.堆优化版dijstra

查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=2e6+10;
bool sign[N];
int h[N],e[N],ne[N],w[N],idx,n,m;
int dis[N];
typedef pair<int,int> PII;
int a[1000000];
void add(int x,int y,int z)
{
    e[idx]=y;
    w[idx]=z;
    ne[idx]=h[x];
    h[x]=idx++;
}
int djs()
{
    for(int i=0;i<=n;i++)dis[i]=LLONG_MAX/2;
    dis[1]=0;
    priority_queue<PII,vector<PII>,greater<PII>> p;
    p.push({0,1});
    while(p.size())
    {
        PII t=p.top();
        p.pop();
        int dian=t.second,distance=t.first;
        if(sign[dian])continue;
        sign[dian]=true;
        for(int i=h[dian];i!=-1;i=ne[i])
        {
            int j=e[i];
            if(dis[j]>distance+w[i])
            {
                dis[j]=distance+w[i];
                p.push({dis[j],j});
            }
        }
    }
    if(dis[n]==LLONG_MAX/2)return -1;
    return dis[n];
}
signed main()
{
    memset(h,-1,sizeof h);
    cin>>n>>m;
    for(int i=1;i<=n;i++)cin>>a[i];
    for(int j=1;j<=m;j++)
    {
        int x,y,z;
        cin>>x>>y>>z;
        add(x,y,z);
    }
    cout<<djs();
    return 0;
}

二:Bellman-Ford(图中不能包含权值总和为负的回路)

1.Bellman-Ford算法

查看代码
 struct Edge {
  int u, v, w;
};
vector<Edge> edge;
int dis[MAXN], u, v, w;
const int INF = 0x3f3f3f3f;

bool bellmanford(int n, int s) {
  memset(dis, 0x3f, sizeof(dis));
  dis[s] = 0;
  bool flag = false; 
  for (int i = 1; i <= n; i++) {
    flag = false;
    for (int j = 0; j < edge.size(); j++) {
      u = edge[j].u, v = edge[j].v, w = edge[j].w;
      if (dis[u] == INF) continue;
      if (dis[v] > dis[u] + w) {
        dis[v] = dis[u] + w;
        flag = true;
      }
    }
    if (!flag) {
      break;
    }
  }
  return flag;
}

2.SPFA队列优化(仅适用有父权边的图

查看代码
#include<bits/stdc++.h>
using namespace std;
const int N=2e6+10;
bool sign[N];
int h[N],e[N],ne[N],w[N],vis[N],idx,n,m,s,t;
int dis[N];
void add(int x,int y,int z)
{
    e[idx]=y;
    w[idx]=z;
    ne[idx]=h[x];
    h[x]=idx++;
}
queue<int>q;
int spfa(int s,int t)
{
    memset(dis,0x3f,sizeof dis);
    memset(vis,0,sizeof vis);
    dis[s]=0;
    vis[s]=1;
    q.push(s);
    while(!q.empty())
    {
        int x=q.front();
        q.pop();
        vis[x]=0;
        for(int i=h[x];i!=-1;i=ne[i])
        {
            int y=e[i];
            if(dis[y]>dis[x]+w[i])
            {
                dis[y]=dis[x]+w[i];
                if(!vis[y])
                {
                    q.push(y);
                    vis[y]=1;
                }
            }
        }
    }
    if(dis[t]>=0x3f3f3f3f)return -1;
    else return dis[t];
}
int main()
{
    memset(h,-1,sizeof h);
    cin>>n>>m>>s>>t;
    for(int j=1;j<=m;j++)
    {
        int x,y,z;
        cin>>x>>y>>z;
        add(x,y,z);
        add(y,x,z);
    }
    cout<<spfa(s,t);
    return 0;
}

三:Floyd

查看代码
 for (k = 1; k <= n; k++) {
  for (x = 1; x <= n; x++) {
    for (y = 1; y <= n; y++) {
      f[x][y] = min(f[x][y], f[x][k] + f[k][y]);
    }
  }
}
posted @ 2024-04-25 22:31  伊芙加登  阅读(5)  评论(0编辑  收藏  举报