POJ - 2387(Dijkstra)

版权声明:如需转载,私聊博主 https://blog.csdn.net/lylzsx20172018/article/details/91346976

前提:经典的算法要经常看,经常复习,遇到比赛时才能得心应手
题目链接:https://cn.vjudge.net/contest/305866#problem/E
问题:求1到n的最短路径
单元最短路径:指定一个点(源点)到其余各个顶点的最短路径问题
Sample Input

5 5
1 2 20
2 3 30
3 4 20
4 5 20
1 5 100

Sample Output

90

第一个5是5条边,第二个5是5个点。
下面是5条边的数据
1---->2距离为20
2---->2距离为30
以此类推。。。

Dijkstra算法的步骤:
**1.**二维数组e储存顶点之间边的关系
一维数组dis储存1号顶点到其余各个顶点的初始路程
**2.**每次找到离源点(题中的1号顶点)最近的一个顶点,然后以该顶点为中心进行扩展,最终得到源点到其余所有点的最短路径
(1)所有顶点分成两部分:已知最短路径的顶点集合p和未知最短路径的顶点集合Q
book[i]=1表示i在p集合中,最初p中只有源点
(2)有源点直接到达的点dis[i]设为e[s][i],不能直接到达设为无穷大
(3)从Q中选择一个离源点最近的一个点加入p中,并进行松弛操作
(4)Q为空,算法结束

代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define inf 0x3f3f3f3

int e[1002][1002],dis[1005],book[1002];

int main()
{
    int T,N,mi; //T条路  N个点
    scanf("%d %d",&T,&N);
    memset(book,0,sizeof(book));
    int a,b,c;
    for(int i=1; i<=N; i++){
        for(int j=1; j<=N; j++){
            if(i==j)e[i][j]=0;  //初始化
            else
                e[i][j]=inf;
        }
    }
    for(int i=0; i<T; i++){
        scanf("%d %d %d",&a,&b,&c);
        if(c<e[a][b]){
            e[a][b]=c;  //这个地方特别注意,不同的题目有不同的要求,看清是双向还是单向,若有重复的,要最小的
            e[b][a]=c;
        }
    }
    for(int i=1; i<=N; i++)
        dis[i]=e[1][i];
    book[1]=1;
    for(int i=1; i<=N-1; i++){
        mi=inf;
        int u;
        for(int j=1; j<=N; j++){
            if(mi>dis[j]&&book[j]==0) //找到离原点最近的点
            {
                mi=dis[j];
                u=j;
            }
        }
        book[u]=1;
        for(int k=1; k<=N; k++){     //松弛操作
            if(dis[k]>dis[u]+e[u][k])
                    dis[k]=dis[u]+e[u][k];

        }
    }
    printf("%d\n",dis[N]);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/lylzsx20172018/article/details/91346976
今日推荐