Loliko_LinawZ

导航

 
给定一个n个点m条边的有向图,图中可能存在重边和自环,所有边权均为正值。

请你求出1号点到n号点的最短距离,如果无法从1号点走到n号点,则输出-1。

输入格式
第一行包含整数n和m。

接下来m行每行包含三个整数x,y,z,表示存在一条从点x到点y的有向边,边长为z。

输出格式
输出一个整数,表示1号点到n号点的最短距离。

如果路径不存在,则输出-1。

数据范围
1≤n≤500,
1≤m≤105,
图中涉及边长均不超过10000。

输入样例:
3 3
1 2 2
2 3 1
1 3 4
输出样例:
3

 

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;

const int N = 510;

int n, m;
int g[N][N], dist[N];   //g存储邻接矩阵  dist存储每个点到起点的最短距离
bool st[N];     //判断当前点是否松弛过

int Dijkstra()
{
    memset(dist, 0x3f, sizeof dist);    //存储每个点到起点的距离是无穷
    dist[1] = 0;        //起点到自身的距离是0
    
    for(int i = 0; i < n; i++)  //迭代n次找到距离起点最近的点
    {
        int t = -1;     //t=-1是为了确定起点 存储当前访问的点
        for(int j = 1; j <= n; j ++)
            if(!st[j] && (t == -1 || dist[t] > dist[j]))    //如果当前节点没有被松弛 并且 该点大于当前存储点到起点的距离
                t = j;      //就更新当前节点到起点的距离
        
        st[t] = true;   //标记该点已经松弛
        
        for(int j = 1; j <= n; j++)
            dist[j] = min(dist[j], dist[t] + g[t][j]);   //这里更新每个点到相邻点的距离
    }
    
    if(dist[n] == 0x3f3f3f3f)   return -1;  //如果不存在最短距离返回-1 0x3f3f3f3f即无穷 这里需要4个字节存储所以要4个3f
    return dist[n];     //返回该点到点n的最短距离
}


int main()
{
    memset(g, 0x3f, sizeof g);
    scanf("%d%d", &n, &m);
    
    while(m -- )
    {
        int x, y, z;
        scanf("%d%d%d", &x, &y, &z);
        g[x][y] = min(g[x][y], z);      //如果存在重边,那取权重较小的一条边
    }
    
    printf("%d\n", Dijkstra());
    return 0;
}
View Code

 

两次迭代的时间复杂度是O(n²) 这里可以通过手写堆来优化更新节点这一过程 让时间复杂度降低到O(mlogn)

还有需要修改的地方往后再补充(*^-^)ρ

 

posted on 2020-09-17 15:07  数码暴龙猪  阅读(77)  评论(0)    收藏  举报