1420:Dijkastra(II)
时间限制: 1000 ms 内存限制: 131072 KB
提交数: 4202 通过数: 659
【题目描述】
给定一个无向连通图,求从1到n的最短路。
【输入】
第一行两个整数n,m,代表点数和边数;
接下来m行,每行三个整数s,t,d,代表从s到t有一条长度为d的无向边。
【输出】
输出一个整数表示最短距离。
【输入样例】
2 3
1 2 1
1 2 3
2 2 0
【输出样例】
1
【提示】
【数据规模及约定】
N≤200000,M≤400000,1≤S,T≤N,0≤D≤109N≤200000,M≤400000,1≤S,T≤N,0≤D≤109
坑点:因为1->n的最大路径长度应该是n * d(也就是10^14)而不是d,所以要开long long!并且正因如此dis的初始化也要由memset承担!
#include <bits/stdc++.h>
#define int long long
using namespace std;
int h[500001],vtx[5000001],nxt[5000001],w[5000001],idx,dis[500001],vis[500001],pre[500001],n,m,s,t,u,v,wt;
//vis:节点被点亮
//dis:从起点开始到任意一点的距离
//pre:被更新的前驱
struct node
{
int u,v,d;//u->v的权重d
};
bool operator < (node a,node b)
{
return a.d >= b.d;
}
priority_queue <node> nd;
void dij(int s)
{
dis[s] = 0;
node tmp;
tmp.u = s;
tmp.v = s;
tmp.d = 0;
nd.push(tmp);
while(!nd.empty())
{
//在nd优先队列里面取出队首 队首的特征就是距离最短的哪个
tmp = nd.top();
nd.pop();
int t = tmp.v;
if(vis[tmp.v] == 1) continue;//如果链接点已经被访问过,就跳过
//如果没有被点亮,需要遍历这个点的所有邻接点.
vis[t] = 1;//这个t点被点亮
//t点为起点,去更新他链接的dis值
int p = h[t];//t点链表的下标
while(p != -1)//遍历整个链表
{
if(vis[vtx[p]] == 0)//t的邻接点没有被点亮
{
if(dis[t] + w[p] < dis[vtx[p]])
{
tmp.u = t;
tmp.v = vtx[p];
tmp.d = dis[t] + w[p];
nd.push(tmp);
dis[vtx[p]] = dis[t] + w[p];
pre[vtx[p]] = t;
}
}
p = nxt[p];
}
}
}
void addEdge(int a,int b,int c)
{
vtx[idx] = b;
nxt[idx] = h[a];
w[idx] = c;
h[a] = idx++;
}
signed main()
{
memset(h,-1,sizeof(h));
scanf("%lld%lld",&n,&m);
s = 1;
t = n;
for(int i = 1; i <= n; i++) pre[i] = i;
//把所有点初始化成最大
memset(dis,0x3f,sizeof(dis));
//读入所有边
for(int i = 1; i <= m; i++)
{
scanf("%lld%lld%lld",&u,&v,&wt);
addEdge(u,v,wt);
addEdge(v,u,wt);
}
dij(s);//从起点开始做dij算法
cout<<dis[t];
return 0;
}