图的最短路径


前言


提示:以下是本篇文章正文内容,下面案例可供参考

一、dijkstra一般迪杰克斯拉

#include <iostream>
#include <climits>//头文件(用于INT_MAX)因为int的最大值记不住
using namespace std;
int a[1005][1005];//邻接矩阵
int d[1005];//存放最短路径
bool v[1005];//标记是否访问过
int n,m,cnt;//n为顶点个数,m为有几条边,minx为最小路径(一般初始化为inf),cnt为源点(初始点)
int main()
{
    cin>>n>>m>>cnt;//输入n,m,cnt
    for(int i=1;i<=n;i++){//初始化邻接表,当i==j时为0,否则为INX_MAX(也就是int类型的最大值)
        for(int j=1;j<=n;j++){
            if(i==j)
            a[i][j]=0;
            else
            a[i][j]=INT_MAX;
        }
    }
    for(int i=1;i<=m;i++){
        int x,y,z;//输入邻接表的值
        cin>>x>>y>>z;//表示的是x点到y点的权值
        a[x][y]=z;//有向图
       // a[y][x]=z;//无向图
    }
    for(int i=1;i<=n;i++){
        d[i]=a[cnt][i];//初始化源点到每个点的权值,若不连通则为INT_MAX
    }
    v[cnt]=1;//将源点设为以访问
    //dijkstra算法核心代码
    for(int i=1;i<=n-1;i++) {
        int minx = INT_MAX, k;//最短路径赋初值
        for (int j = 1; j <= n; j++) {//遍历点
            if (!v[j] && d[j] < minx) {//如果该点未被访问,得出最短路径
                minx = d[k = j];//记录这个点能用最短路径到达下一个点(点的序号)
            }
        }
        v[k] = 1;//将这个点设置为已访问
        for (int j = 1; j <= n; j++) {
            if (a[k][j] < INT_MAX) {//注意:k点到j点的权值不能大于INT_MAX
                if (d[j] > d[k] + a[k][j]) {//如果先到达k点再到达j点的路径,比直接到达j点的路径要短
                    d[j] = d[k] + a[k][j];//就将这个最短路径记录下来,而不是用本身的d[j]
                }
            }
        }
    }
    for(int i=1;i<=n;i++){
        cout<<d[i]<<" ";//最后输出源点到图里各个点的最短路径
    }
    return 0;
}

二、dijkstra 链式星存图+优先队列+堆优化

代码如下(示例):

#include <iostream>
#include <queue>
#include <climits>
#include <utility>
using namespace std;
const int N=1e5+5;
const int M=2e5+5;
int head[N],nxt[M],to[M],val[M],cnt;
int d[N],v[N],n,m,s;
priority_queue<pair<int,int> > q;
void add(int a,int b,int c){
    nxt[++cnt]=head[a];
    to[cnt]=b;
    val[cnt]=c;
    head[a]=cnt;
}
void dijkstra(){
    for(int i=1;i<=n;i++) d[i]=INT_MAX;
    d[s]=0;
    q.push(make_pair(0,s));
    while(!q.empty()){
        int u=q.top().second;
        q.pop();
        if(v[u]) continue;
        v[u]=1;
        for(int i=head[u];i;i=nxt[i]){
            int v=to[i];
            int w=val[i];
            if(d[v]>d[u]+w){
                d[v]=d[u]+w;
                q.push(make_pair(-d[v],v));
            }
        }
    }
}
int main()
{
    cin>>n>>m>>s;
    for (int i = 1; i <=m ; ++i) {
        int u,v,w;
        cin>>u>>v>>w;
        add(u,v,w);
    }
    dijkstra();
    for (int i = 1; i <=n ; ++i) {
        if(d[i]==0x3f3f3f3f)
            cout<<2147483647<<' ';
        else
            cout<<d[i]<<' ';
    }
    return 0;
}

三、floyd弗洛伊德

代码如下(示例):

#include<bits/stdc++.h>
using namespace std;
#define inf 1234567890
#define maxn 10005
inline int read()
{
    int x=0,k=1; char c=getchar();
    while(c<'0'||c>'9'){if(c=='-')k=-1;c=getchar();}
    while(c>='0'&&c<='9')x=(x<<3)+(x<<1)+(c^48),c=getchar();
    return x*k;
}//快读
int a[maxn][maxn],n,m,s;
inline void floyd()
{
    for(int k=1;k<=n;k++)
        //这里要先枚举k(可以理解为中转点)
    {
        for(int i=1;i<=n;i++)
        {
            if(i==k||a[i][k]==inf)
            {
                continue;
            }
            for(int j=1;j<=n;j++)
            {
                a[i][j]=min(a[i][j],a[i][k]+a[k][j]);
                //松弛操作,即更新每两个点之间的距离
                //松弛操作有三角形的三边关系推出
                //即两边之和大于第三边
            }
        }
    }
}
int main()
{
    n=read(),m=read(),s=read();
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        {
            a[i][j]=inf;
        }
    }
    //初始化,相当于memset(a,inf,sizeof(a))
    for(int i=1,u,v,w;i<=m;i++)
    {
        u=read(),v=read(),w=read();
        a[u][v]=min(a[u][v],w);
        //取min可以对付重边
    }
    floyd();
    a[s][s]=0;
    for(int i=1;i<=n;i++)
    {
        printf("%d ",a[s][i]);
    }
    return 0;
}

四、floyd

#include "iostream"
const int N=1e4+5;
const int inf=1234567890;
using namespace std;
int a[N][N],n,m,s;
bool v[N];
void floyd(){
    for (int k = 1; k <=n ; ++k) {
        for (int i = 1; i <=n ; ++i) {
            if(i==k||a[i][k]==inf) continue;
            for (int j = 1; j <=n ; ++j) {
                a[i][j]=min(a[i][j],a[i][k]+a[k][j]);
            }
        }
    }
}
int main()
{
    cin>>n>>m>>s;
    for (int i = 1; i <=n ; ++i) {
        for (int j = 1; j <=n ; ++j) {
            if(i==j)
                a[i][j]=0;
            else
                a[i][j]=inf;
        }
    }
    for (int i = 1; i <=m ; ++i) {
        int u,v,w;
        cin>>u>>v>>w;
        a[u][v]=min(a[u][v],w);
    }
    floyd();
    for (int i = 1; i <=n ; ++i) {
        cout<<a[s][i]<<' ';
    }
    return 0;
}

五、bellmon-floyed

#include<bits/stdc++.h>
#define INF 0x7fffffff
#define MAXN 10005
#define int long long
using namespace std;
int edge[MAXN][MAXN],dis[MAXN];
int n,m,s;
void BellmanFord(){
    dis[s]=0;
    for(int k=1;k<=n;k++){//一共要进行 n 轮松弛
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                dis[i]=min(dis[i],dis[j]+edge[j][i]);
            }
        }
    }
}signed main(){
    cin>>n>>m>>s;
    for(int i=0;i<=n;i++)dis[i]=INF;
    for(int i=0;i<=n;i++)
        for(int j=0;j<=n;j++)edge[i][j]=INF;
    for(int i=0;i<m;i++){
        int u,v,w;
        cin>>u>>v>>w;
        edge[u][v]=min(edge[u][v],w);
    }BellmanFord();
    for(int i=1;i<=n;i++)cout<<dis[i]<<' ';
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值