Mzc和体委的争夺战(Dijkstra算法的思考与尝试以及与SPFA算法的对比)

Mzc和体委的争夺战

–(Dijkstra算法的思考与尝试以及与SPFA算法的对比)

(来源:Luogu)

题目描述

mzc家很有钱(开玩笑),他家有n个男家丁(做过前三弹的都知道)。但如此之多的男家丁吸引来了我们的体委(矮胖小伙),他要来与mzc争夺男家丁。

mzc很生气,决定与其决斗,但cat的体力确实有些不稳定,所以他需要你来帮他计算一下最短需要的时间。

输入输出格式

输入格式:
第一行有两个数n,m,n表示有n个停留站,m表示共有m条路。

之后m行,每行三个数a[i],b[i],c[i],表示第a[i]个停留站到第b[i]个停留站需要c[i]的时间。(无向)

输出格式:
一行,输出1到m最短时间。

输入输出样例

输入样例#1:
5 8
1 2 3
2 3 4
3 4 5
4 5 6
1 3 4
2 4 7
2 5 8
1 5 100
输出样例#1:
11
说明
n<=2500

Dijkstra算法

–单源最短路

先看一下这个图解,有助于我们更好地回忆这个算法。

这里写图片描述
(GIF来自网络)
值得注意的是该算法要求图中不存在负权边,而这也正是SPFA的优点(有种喧宾夺主的感觉)。
它就是以起始点为中心向外求直接相连的最短路,直到扩展到终点为止。其实主要内容看一看这个图就好了。
对于这个题而言,我们需要注意Dijkstra不会判重边,所以在读入的时候要处理一下,让重边取最短的一条。
接下来展示一下代码:

Dijkstra代码

#include<iostream>
#include<cstring>
using namespace std;
int i,j,k,m,n;
int a[2501][2501];
int f[2501];
int b[2501];

int r()
{
    char ch=getchar();
    int ans=0;
    while(ch<'0'||ch>'9')
    {
        ch=getchar();
    }
    while(ch>='0'&&ch<='9')
    {
        ans*=10;
        ans+=ch-'0';
        ch=getchar();
    }
    return ans;
}

void dijk(int x)
{
    b[x]=1;
    for(int i=1;i<=n;i++)
    {
        if(a[x][i])
        f[i]=a[x][i];
    }
    f[x]=0;
    for(int i=1;i<=n;i++)
    {
        int k=0;
        int minn=0x7fffff,mi;
        for(int j=1;j<=n;j++)
        {
            if(!b[j]&&f[j]<minn)
            {
                minn=f[j];
                mi=j;
            }
        }
        b[mi]=1;
        for(int j=1;j<=n;j++)
        {
            if(minn+a[mi][j]<f[j])
            f[j]=minn+a[mi][j];
        }
    }
}

int main()
{

    n=r(),m=r();
    for(i=1;i<=n;i++)
    f[i]=1000000000;
    memset(a,0x7f,sizeof(a));
    int x,y,z;
    for(i=1;i<=m;i++)
    {
        x=r(),y=r(),z=r();
        if(z<a[x][y])
        {a[x][y]=z;
        a[y][x]=z;}
    }
    dijk(1);
    cout<<f[n];
}

SPFA代码

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<queue>
#include<cstring>
using namespace std;
queue<int>q;
int i,j,m,n,st,en,x,y,w;
int s[2501],gs[2501];
int len[2501];
struct data
{
    int d;
    int v;
    struct data *nxt;
};
struct data a[5000001],*head;
int r()
{
    int ans=0;
    char ch=getchar();
    while(ch<'0'||ch>'9')
    ch=getchar();
    while(ch>='0'&&ch<='9')
    {
        ans*=10;
        ans+=ch-'0';
        ch=getchar();
    }
    return ans;
}
void spfa(int xx)
{
    struct data *p=&a[s[xx]];
    while(!q.empty())
    {
    p=&a[s[q.front()]];
    xx=q.front();
    q.pop();
    while(p!=NULL)
    {
        if(len[p->d]>p->v+len[xx])
        {
        q.push(p->d);
        len[p->d]=p->v+len[xx];
        }
        p=p->nxt;
    }
    }
}
int main()
{
    memset(len,0x7f7f7f,sizeof(len));
    n=r(),m=r(),st=1,en=n;
    len[st]=0;
    for(i=1;i<=m;i++)
    {
        x=r(),y=r(),w=r();
        a[gs[x]].nxt=&a[i*2-1];
        a[gs[y]].nxt=&a[i*2];
        gs[x]=i*2-1;
        gs[y]=i*2;
        if(!s[x]) s[x]=i*2-1;
        if(!s[y]) s[y]=i*2;
        a[i*2-1].d=y,a[i*2-1].v=w;
        a[i*2].d=x,a[i*2].v=w;
    }
    q.push(st);
    spfa(st);
    cout<<len[en];
}

Dijkstra
10ms/35761kB
85ms/35761kB
10ms/35761kB
12ms/35761kB
16ms/35761kB
19ms/35761kB
75ms/35761kB
60ms/35761kB
63ms/35761kB
109ms/35761kB
耗时/内存 459ms , 35761kb
SPFA
4ms/1371kB
3ms/1378kB
2ms/92742kB
7ms/1691kB
4ms/1433kB
403ms/92742kB
164ms/5226kB
39ms/2367kB
107ms/5246kB
6ms/1703kB
耗时/内存 739ms , 92742kb
这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值