题意:
顶点数 N ( 1 < = N < = 1000 ) (1<= N <= 1000) (1<=N<=1000),边数 M ( 1 < = M < = 2000 ) (1 <= M <= 2000) (1<=M<=2000),问从固定点 N 走到 固定点 1 的最短路径。
思路:
- 题意很明显求最短路,这里数据范围也不大,我选用了 SPFA算法,复杂度 O ( k m ) O(km) O(km) 。
- 值得注意的是,用链式前向星存储图,边要开 2 ∗ M 2*M 2∗M的空间大小,这里 RE 了 2 次才找出。
#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const int N=5e3+10;
const int inf=0x3f3f3f3f;
int n,m; //点数,边数
int dist[N]; //存储 n 到各点的距离
bool vis[N]; //是否在队列里
struct edge{
int to, w,next;
}e[N];
int h[N],tot;
void add(int u,int v,int w)
{
e[tot].to = v;
e[tot].w = w;
e[tot].next = h[u];
//e[tot] = (edge){v,w,h[u]}; //这里 C++ 提交 CE了
h[u] = tot++;
}
void SPFA(int u)
{
memset(dist,inf,sizeof dist);
queue<int> q;
q.push(u);
dist[u]=0;
vis[u]=true;
while(!q.empty())
{
int t=q.front();
q.pop();
vis[t]=false; //可能再次入队
for(int i=h[t];i!=-1;i=e[i].next)
{
int j=e[i].to;
if(dist[j]>dist[t]+e[i].w)
{
dist[j]=dist[t]+e[i].w; //进行松弛
if(!vis[j]) //不会重复入队
{
q.push(j);
vis[j]=true;
}
}
}
}
}
int main()
{
int u,v,w;
cin>>m>>n;
memset(h,-1,sizeof h);
for(int i=1;i<=m;i++)
{
cin>>u>>v>>w;
add(u,v,w); //无向图加两次边
add(v,u,w);
}
SPFA(n);
cout<<dist[1]<<endl;
return 0;
}