SSL-ZYC 【模板】单源最短路径 【SPFA】

题目大意:
求出一个点到其他所有点的最短路径。

Input

4 6 1
1 2 2
2 3 2
2 4 1
1 3 5
3 4 3
1 4 4

Output

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),然后利用模板库queue构造队列,利用邻接表加速,依次访问每个点,更新最短路,最终输出加一个判断就可以了。

#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;
}
posted @ 2018-06-24 08:27  全OI最菜  阅读(100)  评论(0编辑  收藏  举报