题目传送门:https://www.luogu.org/problemnew/show/P3371
题意:
有n个点,m条边,一个起点st,求st到每个点的最短路径的长度。
思路1:
spfa。
代码:
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
queue<int> f;
struct node{int x,y,z,next;} a[500010];
int last[10010],dis[10010];
bool bz[10010];
int n,m,st,len=0;
void ins(int x,int y,int z)
{
a[++len].x=x;a[len].y=y;a[len].z=z;a[len].next=last[x];last[x]=len;
}
int spfa()
{
memset(bz,true,sizeof(bz));
bz[st]=false;
memset(dis,63,sizeof(dis));
dis[st]=0;
f.push(st);
while(!f.empty())
{
int x=f.front();
f.pop();
bz[x]=true;
for(int i=last[x];i;i=a[i].next)
{
int y=a[i].y;
if(dis[x]+a[i].z<dis[y])
{
dis[y]=dis[x]+a[i].z;
if(bz[y])
{
bz[y]=false;
f.push(y);
}
}
}
}
}
int main()
{
int x,y,z;
scanf("%d %d %d",&n,&m,&st);
for(int i=1;i<=m;i++)
{
scanf("%d %d %d",&x,&y,&z);
ins(x,y,z);
}
spfa();
for(int i=1;i<=n;i++)
printf("%d ",dis[i]<1061109567?dis[i]:2147483647);
}
思路2:
spfa+SLF优化。
所谓SLF优化指如果当前经过松弛的dis[y]小于队列首,就加入队首,否则加入队尾。
用STL中的deque(双端队列)比较好用,建议随时打上(卡卡常,大佬请无视)。
PS:LLL优化蒟蒻表示不会(据说效果不明显,大佬请无视)。
代码:
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
deque<int> f;
struct node{int x,y,z,next;} a[500010];
int last[10010],dis[10010];
bool bz[10010];
int n,m,st,len=0;
void ins(int x,int y,int z)
{
a[++len].x=x;a[len].y=y;a[len].z=z;a[len].next=last[x];last[x]=len;
}
int spfa()
{
memset(bz,true,sizeof(bz));
bz[st]=false;
memset(dis,63,sizeof(dis));
dis[st]=0;
f.push_back(st);
while(!f.empty())
{
int x=f.front();
f.pop_front();
bz[x]=true;
for(int i=last[x];i;i=a[i].next)
{
int y=a[i].y;
if(dis[x]+a[i].z<dis[y])
{
dis[y]=dis[x]+a[i].z;
if(bz[y])
{
bz[y]=false;
if(!f.empty()&&dis[y]<dis[f.front()]) f.push_front(y); else f.push_back(y);
}
}
}
}
}
int main()
{
int x,y,z;
scanf("%d %d %d",&n,&m,&st);
for(int i=1;i<=m;i++)
{
scanf("%d %d %d",&x,&y,&z);
ins(x,y,z);
}
spfa();
for(int i=1;i<=n;i++)
printf("%d ",dis[i]<1061109567?dis[i]:2147483647);
}
思路3:
dijkstra+堆优化。
代码:
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
struct node1
{
int id,d;
friend bool operator <(node1 x,node1 y)
{
return x.d>y.d;
}
};
priority_queue<node1> f;
struct node2{int x,y,z,next;} a[500010];
int last[10010],dis[10010];
bool bz[10010];
int n,m,st,len=0;
void ins(int x,int y,int z)
{
a[++len].x=x;a[len].y=y;a[len].z=z;a[len].next=last[x];last[x]=len;
}
void dijkstra()
{
memset(bz,true,sizeof(bz));
memset(dis,63,sizeof(dis));
dis[st]=0;
f.push((node1){st,0});
while(!f.empty())
{
int x=f.top().id,p=f.top().d;
f.pop();
if(!bz[x]) continue;
bz[x]=false;
dis[x]=p;
for(int i=last[x];i;i=a[i].next)
{
int y=a[i].y;
if(dis[x]+a[i].z<dis[y])
{
dis[y]=dis[x]+a[i].z;
f.push((node1){y,dis[y]});
}
}
}
}
int main()
{
int x,y,z;
scanf("%d %d %d",&n,&m,&st);
for(int i=1;i<=m;i++)
{
scanf("%d %d %d",&x,&y,&z);
ins(x,y,z);
}
dijkstra();
for(int i=1;i<=n;i++)
printf("%d ",dis[i]<1061109567?dis[i]:2147483647);
}
建议用思路2(如果不会,也可以用思路1)和思路3,比较快。