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