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

来源:互联网 发布:越狱录屏软件 编辑:程序博客网 时间:2024/06/03 22:00

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
这里写图片描述

原创粉丝点击