Dijkstra算法模板

#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
const int inf=1<<29;
const int N=1001;
int n,m,d[N],w[N][N];
bool vis[N];
void dij()
{
    for(int i=1; i<=n; i++)//把从起点到其余每个点的距离设为无穷大,方便此后的松弛操作
        d[i]=inf;
    d[1]=0;//以1为起点
    for(int i=0; i<n; i++)//确保不会遗漏松弛,循环n次(因为每次只取当前与原点距离最小值,每个值都要遍历一遍)
    {
        int now=inf;
        int x;
        for(int j=1; j<=n; j++)//从前到后,把起点到每个点的距离都拿出来比一遍(每一次循环,距离都会有更新)
        {
            if(!vis[j]&&now>d[j])//vis避免前面已经比过了的最小值的点重复比较
            {
                //一直找出此时离起点最近的点,以此点为基础,向下找其他点到该点的距离,
                now=d[j];
                x=j;
            }
        }
       // printf("x=%d\n",x);
        vis[x]=1;
        for(int j=1; j<=n; j++)//从x点到其他所有点,全部遍历,进行距离的更新(松弛)操作,
        {
            //!vis[j]避免与前面的最小点重复更新
            if(!vis[j]&&d[j]>d[x]+w[x][j])//如果(这一点到x的距离加x到起点的距离)小于之前存的此点到起点的距离
            {
                d[j]=d[x]+w[x][j];//则更新成新的距离
                //printf("d[%d]=%d\n",j,d[j]);
            }
        }
    }

}
int main()
{
    while(~scanf("%d%d",&n,&m))//点数,边数
    {
        memset(vis,0,sizeof(vis));
        for(int i=1; i<=n; i++)
        {
            for(int j=1; j<=n; j++)
            {
                w[i][j]=inf;//点i到点j的距离全部初始化为无穷大
            }
        }
        while(m--)
        {
            int u,v,c;
            scanf("%d%d%d",&u,&v,&c);//起点,终点,权值
            if(c<w[u][v])
                w[u][v]=w[v][u]=c;//无向图付出权值
        }
        dij();
        for(int i=2; i<=n; i++)//全部输出每个点到起点的最小值
        {
            printf("%d %d\n",i,d[i]);
        }
    }
    return 0;
}
/*
input

7 12
1 2 24
1 3 8
1 4 15
2 5 6
3 5 7
3 6 3
4 7 4
5 7 9
6 5 2
6 7 3
6 4 5
7 2 3

output
2 17
3 8
4 15
5 13
6 11
7 14*/

 

局限性:当A到A的距离为0 代码切入到子函数最下方,A到B的距离更新为3,A到C的距离更新为2,再循环找出C点,标记C点已经不能在更新,这是有向图,C不能再向下更新,回去再循环,找出B点,,当B点准备向下更新时,因为之前C点已经被标记,这里会直接跳过C点,不能对其更新,算出的结果是2,但实际上是3-2=1,所以这个算法不能算带有负权值的图

转载于:https://www.cnblogs.com/tianmin123/p/4774794.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值