1382:最短路(Spfa)
时间限制: 1000 ms 内存限制: 65536 KB
提交数:15578 通过数: 4682
【题目描述】
给定 M� 条边, N� 个点的带权无向图。求 11到 N� 的最短路。
【输入】
第一行:N,M(N<=100000,M<=500000)�,�(�<=100000,�<=500000);
接下来M�行33个正整数:ai,bi,ci表示ai,bi之间有一条长度为ci的路,ci<=1000��,��,��表示��,��之间有一条长度为��的路,��<=1000。
【输出】
一个整数,表示 11 到 N� 的最短距离。
【输入样例】
4 4
1 2 1
2 3 1
3 4 1
2 4 1
【输出样例】
2
【提示】
【样例解释】
注意图中可能有重边和自环,数据保证 11 到 N� 有路径相连。
//1382:最短路(Spfa) ;链式前向星 创建图,优先队列找最小的dis结点u,通过u更新u的邻边v结点到起始结点的距离dis【v】,注意:e的规模边的2倍空间
#include<bits/stdc++.h>
using namespace std;
// 链式前向星 创建图,效率最高,只需要按照边的条数创建
struct edge ///u-v 有一条边
{
int to; // 边的终止结点
int w; // u-v距离为w
int next; // u的下一个边的序号
}e[1000005];// 边的条数
int head[100000];//记录这个结点 的起始邻边 边的的序号
int cnt=0;// 边从0开始
void addedge(int x,int y,int z)
{
cnt++; // 第一条邻边的序号
e[cnt].to=y; // 终止结点为y
e[cnt].w=z; // 距离为在
e[cnt].next=head[x]; // 下一条li
head[x]=cnt;// x的临边记录下一条边的序号
}
int n,m; // n 是顶点数,m是边数
typedef struct node
{
long long d; // 距离
int num; // 序号
bool operator<(const node &nd1)const{
return nd1.d<d; // 从大到小
}
}node;
long long dis[100005];// 每个点到起始结点的距离
int visit[100005];// 标记结点是否已经访问
const int inf=0x3f3f3f3f;
void djk()
{
memset(dis,inf,sizeof(dis)); // 默认距离无穷大
dis[1]=0; // 起始到自己的距离为0
priority_queue<node> qu; // dis 从小到大
node nd;
nd.d=0;
nd.num=1;
qu.push(nd); // 起始结点进队列
while(!qu.empty()) //
{
node nf=qu.top();// 优先队列操作入栈所
qu.pop(); //删掉
int u=nf.num;// 找到了没有访问的,最小的dis的序号
// if(visit[u]==1)
// continue;
visit[u]=1; // 标记已经访问
// 通过u (起始u点,可能更新到u的邻边结点v的距离)
for(int j=head[u];j>0;j=e[j].next) // j 是u邻边的边序号
{
int v=e[j].to;// v是u的邻边结点
if(visit[v]==0&&dis[v]>dis[u]+e[j].w) // 到v的距离,通过uv这条边更新
{
dis[v]=dis[u]+e[j].w;// 更新距离
qu.push(node{dis[v],v}); // v 结点进队列
}
}
}
}
int main()
{
cin>>n>>m;
int i,j;
for(i=1;i<=m;i++)
{
int x,y,z;
scanf("%d%d%d",&x,&y,&z);//cin>>x>>y>>z;
if(x==y)
continue;
addedge(x,y,z);
addedge(y,x,z);
}
djk();
printf("%lld",dis[n]);
}