最短路-dij

最短路,也是单源最短路,能够求出从一个点到达其他所有点的最短距离(n是点,m是边E是不确定)

算法有 Dij(O(n2)很稳定)  SPFA(O(nEnm),据说有很多优化方案,但每种方案又有对应卡你过不去的策略,不建议使用但是据说网络流必须用他) FloydO(n3),内部含有dp思想,平时90%不用)Bellman主要判断是否有负环(O(nm)Dij+堆(O(mlgm)以后解决最短路常用方法,高效又稳定)

其中Dij主要用于正权图,如果有负环需要用SPFABellman

说一下DIJ                       

 数组定义f[x][y]代表 xy中间有一条路 (因此双向边的时候一定记着把f[y][x]也设置一下)

Vis[x]代表是否走到x

Dis[x]代表当前到达x的最短距离

DIj的过程其实就是一直找连通块外中,且只经过连通块内的点,距离源点(最开始连通块只有起始节点)最近的点,因为这个点一定不能通过其他点来节约距离,所以这个点相当于求出最短路了,由于这个点也加入连通块了,所以要更新DIs(也就是距离当前连通块最近的点)

 

很多同学不会判-1,有几种方法

  1. 初始化是INF,最后判断DIs是否是INF即可
  2. 如果visn】没有更改,说明n没走过,也是-1
  3. 当函数跑到n以后,直接返回dis[n],否则返回-1

 

#include<stdio.h>

#include<string.h>

#include<algorithm>

using namespace std;

#define rep(i,j,k) for(int i=j;i<=k;++i)

#define INF 0x3f3f3f3f

#define MAXN 1005

int f[MAXN][MAXN];

int dist[MAXN],dis[MAXN];

bool vis[MAXN];

int n;

void dijkstra(int x)

{

    int i,j;

    memset(vis,true,sizeof(vis));

    rep(i,1,n)

    dist[i]=f[x][i];

    vis[x]=false;

    int id;

    rep(i,1,n-1)

    {

        id=-1;

        rep(j,1,n)

        {

            if(vis[j]&&(id==-1||dist[j]<dist[id]))

                id=j;

        }

        if(id==-1)

            return ;

        vis[id]=false;

        rep(j,1,n)

        {

            if(vis[j]&&dist[id]+f[id][j]<dist[j])

                dist[j]=dist[id]+f[id][j];

        }

    }

}

int main()

{

 

    int m;

    while(scanf("%d %d",&m,&n)!=EOF)

    {

        int a,b,v;

        memset(f,INF,sizeof(f));

        rep(i,1,m)

        {

            scanf("%d %d %d",&a,&b,&v);

            f[a][b]=min(f[a][b],v);

            f[b][a]=min(f[b][a],v);

        }

        dijkstra(1);

        printf("%d\n",dist[n]);

    }

}

 

posted @ 2018-12-22 17:28  注册以后还能改吧  阅读(173)  评论(0编辑  收藏  举报