题目大意:
求出一个点到其他所有点的最短路径。
4 6 1
1 2 2
2 3 2
2 4 1
1 3 5
3 4 3
1 4 4
0 2 4 3
思路:
最短路
思路一:dijkstra
当时还没有学SPFA,看了数据感觉dijkstra可以卡过,于是打了一发dijkstra,结果
也许是我打错了,可能可以得70分。请dalao指教。
#include <iostream>
#include <cstdio>
#include <cstring>
const int inf=99999999;
using namespace std;
int n,m,k,a[10001][10001],b[10001],c[10001],minn,o,x,y;
int main()
{
scanf("%d%d%d",&n,&m,&k);
for (int i=1;i<=m;i++)
{
scanf("%d%d",&x,&y);
scanf("%d",&a[x][y]); //存入有向边
}
b[k]=1;
a[k][k]=0;
for (int i=1;i<=n;i++)
if (a[i][k]>0) c[i]=a[i][k];
else c[i]=inf;
c[k]=0;
for (int j=1;j<=n-1;j++)
{
minn=inf-1;
for (int i=1;i<=n;i++)
if (b[i]==0&&c[i]<minn) //找最短边
{
minn=c[i];
o=i;
}
b[o]=1; //访问
for (int i=1;i<=n;i++)
if (b[i]==0&&c[i]>a[o][i]+c[o]) c[i]=c[o]+a[o][i]; //更新最短路
}
for (int i=1;i<=n;i++)
if (c[i]!=inf) printf("%d ",c[i]);
else printf("2147483647 ");
return 0;
}
思路二:SPFA
这道题的正解就是SPFA。首先用邻接表储存边(用邻接矩阵会MLE,而且那还叫什么SPFA),然后利用模板库构造队列,利用邻接表加速,依次访问每个点,更新最短路,最终输出加一个判断就可以了。
#include <iostream>
#include <cstdio>
#include <queue>
using namespace std;
const int inf=99999999;
int n,m,s,t,k,head[30001],dis[30001],vis[30001],x,y,Dis;
struct edge //邻接表
{
int to,dis,next;
}e[1500001];
void add(int from,int to,int Dis) //建图
{
k++;
e[k].next=head[from];
e[k].to=to;
e[k].dis=Dis;
head[from]=k;
}
void spfa()
{
queue<int> q; //队列
for (int i=1;i<=n;i++) //初始化
{
dis[i]=inf;
vis[i]=0;
}
q.push(s); //加入出发点
vis[s]=1;
dis[s]=0;
while (q.size()) //相当于 while(!q.empty())
{
int u=q.front(); //取出队首
q.pop(); //弹出
vis[u]=0; //访问标记
for (int i=head[u];i;i=e[i].next) //邻接表加速
{
int v=e[i].to; //到达点
if (dis[v]>dis[u]+e[i].dis) //更新最短路
{
dis[v]=dis[u]+e[i].dis;
if (!vis[v]) //访问标记
{
vis[v]=1;
q.push(v); //入队
}
}
}
}
}
int main()
{
scanf("%d%d%d",&n,&m,&s);
for (int i=1;i<=m;i++)
{
scanf("%d%d%d",&x,&y,&Dis);
add(x,y,Dis); //建图
}
spfa();
for (int i=1;i<=n;i++)
dis[i]==inf?printf("2147483647 "):printf("%d ",dis[i]); //相当于 if (dis[i]!=inf) printf("%d ",dis[i]); else printf("2147483647 ");
return 0;
}