算法训练 最短路
时间限制:1.0s 内存限制:256.0MB
提交此题 锦囊1 锦囊2
问题描述
给定一个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,保证从任意顶点都能到达其他所有顶点。
/*
模板题,没用优化
*/
# include <iostream>
# include <algorithm>
# include <vector>
# include <string.h>
# include <queue>
# define MAXN 20005
# define INFI 0x3f3f3f3f
using namespace std;
typedef struct Node
{
int v;
int len;
}Node;
int n,m,cnt;
vector<Node > vt[MAXN];
int inque[MAXN];
int num[MAXN];
int lowcost[MAXN];
deque<int > dq;
void init()
{
memset(inque,0,sizeof(inque));
memset(lowcost,0,sizeof(lowcost));
memset(num,0,sizeof(num));
cnt = 0;
for(int i=0; i<=n; ++i)
{
vt[i].clear();
lowcost[i] = INFI;
}
}
int spfa(int x)
{
dq.push_back(x);
lowcost[x] = 0;
inque[x] = 1;
num[x] = 1;
while(!dq.empty())
{
int t = dq.front();
dq.pop_front();
inque[t] = 0;
for(int i=0; i<vt[t].size(); ++i)
{
int ed = vt[t][i].v;
int len = vt[t][i].len;
if(lowcost[ed] > lowcost[t] + len)
{
lowcost[ed] = lowcost[t] + len;
if(!inque[ed])
{
inque[ed] = 1;
dq.push_back(ed);
num[ed]++;
if(num[ed] >= n)
return 1;
}
}
}
}
return 0;
}
int main()
{
// freopen("in.txt","r",stdin);
ios::sync_with_stdio(false);
cin >> n >> m;
Node t;
init();
for(int i=0; i<m; ++i)
{
int a,b,c;
cin >> a >> b >> c;
t.v = b;
t.len = c;
vt[a].push_back(t);
}
spfa(1);
for(int i=2; i<=n; ++i)
{
cout << lowcost[i]<<endl;
}
return 0;
}