记录一个菜逼的成长。。
记下SPFA的两种优化,大牛请无视
SPFA算法有两个优化算法 SLF 和 LLL:
SLF:Small Label First 策略,设要加入的节点是
j
j
j,队首元素为
i
i
i,若
d
i
s
t
(
j
)
<
d
i
s
t
(
i
)
dist(j) < dist(i)
dist(j)<dist(i),则将j插入队首,否则插入队尾。
LLL:Large Label Last 策略,设队首元素为
i
i
i,每次弹出时进行判断,队列中所有dist值的平均值为x,若
d
i
s
t
(
i
)
>
x
dist(i)>x
dist(i)>x则将
i
i
i插入到队尾,查找下一元素,直到找到某一
i
i
i使得
d
i
s
t
(
i
)
<
=
x
dist(i)<=x
dist(i)<=x,则将i出对进行松弛操作。
char str[maxn][maxn];
int vis[maxn][maxn],dis[maxn][maxn],n,m;
int ans[30],sum,cnt;
int dx[] = {-1,-1,0,1,1,1,0,-1},dy[] = {0,1,1,1,0,-1,-1,-1};
deque<PII>q;
void spfa()
{
while(!q.empty()){
PII f = q.front();q.pop_front();
//LLL优化
if(dis[f.fi][f.se] * cnt > sum){
q.push_back(f);
continue;
}
sum -= dis[f.fi][f.se];cnt--;
vis[f.fi][f.se] = 0;
for( int i = 0; i < 8; i++ ){
int nx = f.fi + dx[i],ny = f.se + dy[i];
if(nx < 1 || nx > n || ny < 1 || ny > m)continue;
int w = (str[nx][ny] != str[f.fi][f.se]);
if(dis[nx][ny] > dis[f.fi][f.se] + w){
dis[nx][ny] = dis[f.fi][f.se] + w;
if(!vis[nx][ny]){
vis[nx][ny] = 1;
//SLF优化
if(dis[nx][ny] < dis[q.front().fi][q.front().se]){
q.push_front(mp(nx,ny));
}
else {
q.push_back(mp(nx,ny));
}
sum += dis[nx][ny];cnt++;
}
}
}
}
}
void init()
{
cl(dis,INF);
cl(vis,0);
cl(ans,INF);
sum = cnt = 0;
}