算法训练 最短路

2017-03-04  本文已影响69人  DongBold

问题描述

给定一个n个顶点,m条边的有向图(其中某些边权可能为负,但保证没有负环)。请你计算从1号点到其他点的最短路(顶点从1到n编号)。

输入格式

第一行两个整数n, m。
接下来的m行,每行有三个整数u, v, l,表示u到v有一条长度为l的边。

输出格式

共n-1行,第i行表示1号点到i+1号点的最短路。
样例输入
3 3
1 2 -1
2 3 -1
3 1 2

样例输出

-1
-2

数据规模与约定

对于10%的数据,n = 2,m = 2。
对于30%的数据,n <= 5,m <= 10。
对于100%的数据,1 <= n <= 20000,1 <= m <= 200000,-10000 <= l <= 10000,保证从任意顶点都能到达其他所有顶点。

采用bellman算法求单元最短路径, 因为存在负边, 所以就不使用dijkstra算法

#include <bits/stdc++.h> 
using namespace std;
#define INF 0x3f3f3f3f
#define MAXV 20005
#define MAXE 200005

struct {
    int from;
    int to;
    int cost;
}edge[MAXE];

int dist[MAXV];

int n, m;

bool bellman(int s) {
    memset(dist, 0x3f, sizeof(dist));
    dist[s] = 0;
    int j = 0;
    bool update = false;
    while(true) {
        update = false;
        for (int i = 0; i < m; i++) {
            if (dist[edge[i].from] != INF && dist[edge[i].to] > dist[edge[i].from] + edge[i].cost) {
                dist[edge[i].to] = dist[edge[i].from] + edge[i].cost;
                update = true;
            }
        }
        j++;
        if(!update) return true;
        if(j == m)  return false;
    }
}


int main() {
    int u, v, l;
    scanf("%d%d", &n, &m);
    for (int i = 0; i < m; i++) {
        scanf("%d%d%d", &u, &v, &l);
        u--;
        v--;
        edge[i].from = u;
        edge[i].to = v;
        edge[i].cost = l;
    }
    bellman(0);
    for(int i = 1; i < n; i++) {
        printf("%d\n", dist[i]);
    }
    
    return 0;
}
上一篇下一篇

猜你喜欢

热点阅读