SPFA有两种优化
SPFA算法有两个优化策略SLF和LLL——SLF:Small Label First 策略,设要加入的节点是j,队首元素为i,若dist(j)<dist(i),则将j插入队首,否则插入队尾; LLL:Large Label Last 策略,设队首元素为i,队列中所有dist值的平均值为x,若dist(i)>x则将i插入到队尾,查找下一元素,直到找到某一i使得dist(i)<=x,则将i出队进行松弛操作。 SLF 可使速度提高 15 ~ 20%;SLF + LLL 可提高约 50%。
就拿hdu4725为例:
不优化肯定会超时的。
#include <bits/stdc++.h>
using namespace std;
int n,m,c,k;
const int MAXN=3e5+7;
const int inf=1e9;
vector<pair<int,int>>head[MAXN];
int dis[MAXN],vis[MAXN];
void spfa(int n)
{
for(int i=1; i<=n; ++i)
{
dis[i]=inf;
vis[i]=0;
}
deque<int>q;
q.push_front(1);
dis[1]=0;
int sum = 0,cnt = 0;
while(!q.empty())
{
int u=q.front();
q.pop_front();
if(dis[u]*cnt > sum)
{
q.push_back(u);
continue;
}
vis[u]=0;
sum -= dis[u],cnt--;
for(int i=0,l=head[u].size(); i<l; ++i)
{
int v=head[u][i].first;
int w=head[u][i].second;
if(dis[u]+w<dis[v])
{
dis[v]=dis[u]+w;
if(!vis[v])
{
vis[v]=1;
if(q.empty() || dis[v]<dis[q.front()])q.push_front(v);
else q.push_back(v);
sum += dis[v],cnt++;
}
}
}
}
if(dis[n/3]>=inf)puts("-1");
else printf("%d\n",dis[n/3]);
}
int main()
{
int t;
scanf("%d",&t);
for(int tt=1; tt<=t; ++tt)
{
scanf("%d%d%d",&n,&m,&c);
for(int i=1,l=n*3; i<=l; ++i)
{
head[i].clear();
}
int x;
for(int i=1; i<=n; ++i)
{
scanf("%d",&x);
head[i].push_back(make_pair(x*2-1+n,0));
head[x*2+n].push_back(make_pair(i,0));
}
for(int i=1; i<=n; ++i)
{
head[i*2-1+n].push_back(make_pair(i*2+2+n,c));
head[i*2+1+n].push_back(make_pair(i*2+n,c));
}
int u,v,w;
while(m--)
{
scanf("%d%d%d",&u,&v,&w);
head[u].push_back(make_pair(v,w));
head[v].push_back(make_pair(u,w));
}
printf("Case #%d: ",tt);
spfa(n*3);
}
return 0;
}

本文详细介绍了SPFA算法中的两种优化策略:SLF(Small Label First)和LLL(Large Label Last)。通过这两种策略,可以显著提升算法效率,SLF可使速度提高15~20%,SLF+LLL则可提高约50%。并通过具体实例hdu4725展示了这些优化的实际应用。
2306

被折叠的 条评论
为什么被折叠?



