P3371 【模板】单源最短路径
用的方法是SPFA算法,还利用了链式前向星存储图。
链式前向星:利用结构体进行存储
struct Edge
{
int next,to,dist; //next是存储下一个点,to是这条边所要去的点,dist是边的长度。
}edge[maxm];
存储:
for(int i=1;i<=m;i++){
int a,b,c;
scanf("%d%d%d",&a,&b,&c); //a -> b 长度为c
edge[i].next=head[a];
edge[i].to=b;
edge[i].dist=c;
head[a]=i;
}
eg :存几组数据(1,3,4)(1,5,1)(1,2,1)(2,4,1)(2,5,1)
edge[1].next=head[1]=0 //因为head[1]初值为0
edge[1].to=3
edge[1].dist=4
head[1]=1
edge[2].next=head[1]=1
edge[1].to=5
edge[1].dist=1
head[1]=2
edge[3].next=head[1]=2
edge[1].to=2
edge[1].dist=1
head[1]=3
edge[4].next=head[2]=0
edge[1].to=4
edge[1].dist=1
head[2]=1
edge[5].next=head[2]=1
edge[1].to=5
edge[1].dist=1
head[2]=2
下面是一个访问的循环
for(int i=head[u];i;i=edge[i].next){
int x=edge[i].to;
//所需要执行的操作:
}
循环过程:例如起点为点1(即u=1),head[1]=3,所以i=3,接下来i=edge[3].next=2,然后再进行循环,i=edge[2].next=1,再循环edge[1].next=0,结束循环。 这样点1所要去的点都走了一遍,其他点以此类推 根本看不懂为什么,所以我认为这就是一个固定的模板,所以最短路径还是要把其他算法也学了
接下来就是题目代码:
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <string>
#include <map>
#include <queue>
#include <cstring>
#include <cmath>
const int maxn=10005;
const int maxm=500005;
const int inf=2147483647;
using namespace std;
int n,m,s,num_=0,dis[maxn],vis[maxn],head[maxn];
struct Edge //链式前向星存储
{
int next,to,dist;
}edge[maxm];
void spfa(int s) //SPFA算法
{
for(int i=1;i<=maxn;i++){
dis[i]=inf; //dis记录起点到其他点之间的长度,初值都设为最大
vis[i]=0; //vis记录点是否已经经过
}
dis[s]=0; //起点到起点距离为0
vis[s]=1; //表示起点已经经过
queue <int> q; //开个stl的队列
q.push(s); //起点入队
while (!q.empty()){ //计算每个点到其他点之间的距离,每个点都跑一遍,跑完循环结束
int u=q.front();
q.pop();
vis[u]=0;
for(int i=head[u];i;i=edge[i].next){
int x=edge[i].to;
if(dis[x]>dis[u]+edge[i].dist){
dis[x]=dis[u]+edge[i].dist;
if(!vis[x]){
vis[x]=1;
q.push(x); //点入队
}
}
}
}
}
int main()
{
scanf("%d%d%d",&n,&m,&s);
for(int i=1;i<=m;i++){
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
edge[i].next=head[a];
edge[i].to=b;
edge[i].dist=c;
head[a]=i;
}
spfa(s);
printf("%d",dis[1]);
for(int i=2;i<=n;i++){
printf(" %d",dis[i]);
}
printf("\n");
return 0;
}