算法训练 最短路  
时间限制:1.0s   内存限制:256.0MB
       
问题描述

给定一个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算法,可以处理负边的情况。

#include <iostream>
#include <cstdio>
#include <cstring>
#define max_v 50005
#define max_e 500005
#define INF 0x3f3f3f3f

using namespace std;

struct edge{int from,to,cost;};
edge ee[max_e];//存储每条边的信息
int d[max_v];//表示s到每个顶点的最短距离
int v,e;//顶点数和边数

//返回true计算最短路成功,返回false存在负圈;
bool bellman(int s){
    memset(d,INF,sizeof(d));//赋最大值的技巧
    d[s]=0;
    int j=0;//添加的计数器
    while(true){
        bool update=false;
        for(int i=0;i<e;i++){
            edge et=ee[i];
            if(d[et.from]!=INF&&d[et.to]>d[et.from]+et.cost){
                d[et.to]=d[et.from]+et.cost;
                update=true;
            }
        }
        j++;
        if(!update) return true;
        if(j==v) return false;//当进行第v次循环时,说明存在负圈
    }
}


int main()
{
    int x,y,z;
    scanf("%d %d",&v,&e);
    for(int i=0;i<e;i++){
        scanf("%d %d %d",&x,&y,&z);
        x-=1;
        y-=1;
        ee[i].from=x;
        ee[i].to=y;
        ee[i].cost=z;
        ee[e+i].from=y;
        ee[e+i].to=x;
        ee[e+i].cost=z;
    }
    bellman(0);
    for(int i=1;i<v;i++){
        printf("%d\n",d[i]);
    }
    return 0;
}