You are given a weighted undirected graph. The vertices are enumerated from 1 to n. Your task is to find the shortest path between the vertex1 and the vertex n.
The first line contains two integers n and m (2 ≤ n ≤ 105, 0 ≤ m ≤ 105), where n is the number of vertices and m is the number of edges. Following m lines contain one edge each in form ai, bi and wi (1 ≤ ai, bi ≤ n, 1 ≤ wi ≤ 106), where ai, bi are edge endpoints and wi is the length of the edge.
It is possible that the graph has loops and multiple edges between pair of vertices.
Write the only integer -1 in case of no path. Write the shortest path in opposite case. If there are many solutions, print any of them.
5 6 1 2 2 2 5 5 2 3 4 1 4 1 4 3 3 3 5 1
1 4 3 5
5 6 1 2 2 2 5 5 2 3 4 1 4 1 4 3 3 3 5 1
1 4 3 5
就是一个dijkstra,然后数据量太大用矩阵是存不下的了,所以要用到vector,然后时间复杂度,如果是未优化的dijkstra是 n² ,那么n是10^5,就达到了一百亿的复杂度,这肯定是不行的,所以怎么也要用个优先队列或者斐波纳契堆优化一下降低到n*logn的复杂度,也就是未到10^8,也就是几千万,CF上的评测机还是跑的比较快的,所以也没什么问题。
代码如下:
#include <iostream>
#include <cstdio>
#include <queue>
#include <vector>
using namespace std;
const int Ni = 100005;
const long long INF = 100000000005;
struct node{
int x;
long long d;
node(){}
node(int a,long long b)
{
x = a;
d = b;
}
bool operator < (const node & a) const
{
if(d==a.d)
return x<a.x;
else
return d > a.d;
}
};
vector<node> eg[Ni];
long long dis[Ni], n;
int front[Ni];
void Dijkstra(int s)
{
int i;
for(i = 0; i <= n; i++)
dis[i] = INF;
dis[s] = 0;
priority_queue <node> q;
q.push(node(s, dis[s]));
while(!q.empty())
{
node x = q.top();
q.pop();
for(i = 0; i < eg[x.x].size(); i++)
{
node y = eg[x.x][i];
if(dis[y.x] > x.d + y.d)
{
dis[y.x] = x.d + y.d;
q.push(node(y.x, dis[y.x]));
front[y.x] = x.x;
}
}
}
}
int main()
{
int a,b,m,k,i;
long long d;
int tmp[Ni];
#ifdef llzhh
freopen("in.txt", "r", stdin);
#endif // llzhh
scanf("%d%d",&n,&m);
for(i=0;i<=n;i++)
{
eg[i].clear();
front[i]=i;
}
while(m--)
{
scanf("%d%d%I64d",&a,&b,&d);
eg[a].push_back(node(b,d));
eg[b].push_back(node(a,d));
}
Dijkstra(1);
// printf("%I64d\n",dis[n]);
i = n;
k = 0;
while(i != front[i])
{
tmp[k++] = i;
i = front[i];
}
if(i != 1)
printf("-1\n");
else
{
printf("1 ");
for(i = k - 1; i >= 1; i--)
printf("%d ", tmp[i]);
printf("%d\n", n);
}
return 0;
}
这道题我一开始定义INF是用位运算来定义的,直接定义为2<<60,但是我发现这样会一直报错???不知道是为啥,我觉得应该是可以的,毕竟INF是long long64位,左移60位没道理出错啊,而且这个错误它还不提醒的,直接跑程序的时候会直接卡住然后结束。后来就直接手写了一个10的11次方+5,因为最多有10^5个点,每个点之间的线最大是10^6,乘起来就是10^11。然后就AC了,真是坑啊。