您的位置:首页 > 其它

SPFA的两种优化SLF和LLL

2017-08-02 14:59 309 查看
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