首先呢,阐述一下,这是一道最短路模板题,其实看题也看得出来… …,所以呢,我们先得搞清楚什么是最短路
这道题呢,我们用的是dijkstra(俗称低级科斯拉)
如有未搞懂dijkstra的童鞋,可以先看看这片题解
dijkstra详解
既然是用dijkstra,那就得先想到堆优化(上面链接中也说了)。但是呢,最短路径这类问题,堆优化可以用一个优先队列来代替,即priority_queue (头文件要用 #include )
重载(即 friend bool operator)可将一个符号改成自己需要的作用,但只适用于一定范围中,如在结构体中的重载,就只能在使用到结构体的时候用,且没有原来的作用。而在其他部分还是原来的作用
struct node //结构体名称
{
int a,b; //两个比较变量
friend bool operator < (const node &x,const node &y) //定义
{
return x.a>y.a; //重载
}
}; //注意,这里要在优先队列中用到,所以不需要有数组
最短路径属于图论,而图论不可缺失的就是添边,这时,我们需要用到添边函数addedge了
int to[maxn],val[maxn],head[maxn],ne[maxn],cnt; //to代表从该点到哪个点,val代表边权,ne代表点在数组里的编号,head代表上一个点在数组里的编号,cnt代表现在运行到第几条边了
void edge(int u,int v,int w)//
{
to[++cnt]=v; //添边
val[cnt]=w; //存边权
ne[cnt]=head[u]; //存点编号
head[u]=cnt; //下一个
}
松弛是用每一个还没查询过的点,去看能不能更新最短路,且每个点只能松弛一次
void dijkstra(s) //命名
{
for (int i=1;i<=n;i++)
{
dis[i]=0x7f7f7f7f; //因为是最短路,所以先赋无穷大
}
dis[s]=0; //到自己的距离为0
q.push((node){0,s}); //先将自己入队列,这里用结构体打包了到哪个点以及最短路的值
while(q.size()!=0) //进行操作
{
int x=q.top().b; //拿b队列对顶
q.pop(); //出队
if(flag[x]==1) continue; //若查询过,则不继续松弛
flag[x]=1; //标记一下
for(int i=head[x]; i; i=ne[i]) //开始从当前不为无穷大且没查询过的点中的最短路径点开始松弛
{
if(dis[to[i]]>dis[x]+val[i]) //松弛的精华
{
dis[to[i]]=dis[x]+val[i]; //如果有更优解,则替换成更优解
q.push((node){dis[to[i]],to[i]}); //将最短路入队
}
}
}
}
#include
using namespace std;
struct node
{
int a,b;
friend bool operator < (const node &x,const node &y)
{
return x.a>y.a;
}
};
priority_queue<node> q;
int head[500005],to[500005],val[500005],ne[500005],cnt;
int n,m,s;
long long dis[100005];
bool flag[100005];
void edge(int u,int v,int w)
{
to[++cnt]=v;
val[cnt]=w;
ne[cnt]=head[u];
head[u]=cnt;
}
void dijkstra(int s)
{
for (int i=1;i<=n;i++)
{
dis[i]=0x7f7f7f7f;
}
dis[s]=0;
q.push((node){0,s});
while(q.size()!=0)
{
int x=q.top().b;
q.pop();
if(flag[x]==1) continue;
flag[x]=1;
for(int i=head[x]; i; i=ne[i])
{
if(dis[to[i]]>dis[x]+val[i])
{
dis[to[i]]=dis[x]+val[i];
q.push((node){dis[to[i]],to[i]});
}
}
}
}
int main()
{
scanf("%d%d%d",&n,&m,&s);
for(int i=1;i<=m;i++)
{
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
edge(u,v,w);
}
dijkstra(s);
for(int i=1;i<=n;i++)
printf("%ld ",dis[i]);
return 0;
}
大家可以去看看洛谷的P3371,只需要改一点点就能过哦!