1. 程式人生 > >SPFA和dijkstra優化

SPFA和dijkstra優化

SPFA

  • 單源最短路,好哇

  • 時間複雜度玄

  • 無畏負權邊,容易被卡負環

  • 好打好理解

  • S L F SLF 優化:如果當前要入隊一個點 i

    i ,如果 d i s [ i ]
    < d i s [ q u e [
    h e a d ] ] dis[i] < dis[que[head]]
    (比隊首要優)就放入隊首,否則就放入隊尾

  • L L L LLL 優化:如果當前的出隊的數( q u e [ h e a d ] que[head] ),他的 d i s dis 大於佇列中所有 d i s dis 的平均值,那麼就把 q u e [ h e a d ] que[head] 入隊尾,然後 c o n t i n u e continue

  • 可以用 S T L STL d e q u e deque 來實現 S L F SLF L L L LLL 亂搞就行

inline void spfa()
{
	ll z=0,length=1;
	while (que.size())que.pop_front();
	memset(bz,1,sizeof(bz));
	memset(dis,100,sizeof(dis));
	que.push_front(S),dis[S]=bz[S]=0;
	while (que.size())
	{
		ll now=que.front();
		if (length*dis[now]>z)
		{//LLL優化
			que.pop_front(),que.push_back(now);
			continue;
		}
		--length,z-=dis[now];
		que.pop_front(),bz[now]=1;
		rep(i,now)
		{
			if (dis[now]+len[i]<dis[tov[i]])
			{
				dis[tov[i]]=dis[now]+len[i];
				if (bz[tov[i]])
				{
					bz[tov[i]]=0,z+=dis[tov[i]],++length;
					if (que.empty() || dis[que.front()]<dis[tov[i]])que.push_back(tov[i]);//比隊頭劣則入隊尾
					else que.push_front(tov[i]);//反之則入隊頭
				}
			}
		}
	}
}

dijkstra

  • 單源最短路,更好

  • 時間複雜度 O ( ( n + m ) l o g 2 n ) O((n+m)log_2n) ,很多題目一般可以看成 O ( n l o g 2 n ) O(nlog_2n) 乘上個 3 3 左右的常數

  • 只要沒有負權邊就強大通用

  • 優化用 S T L STL p r i o r i t y priority _ q u e u e queue 就行了

  • 堆優化完比 S P F A SPFA 還短,以後都不打SPFA.jpg

struct node
{
	ll x,y;
	bool operator <(const node &a)const
	{
		return a.y<y;
	}
};
priority_queue<node>que;

inline void dijkstra()
{
	while (!que.empty())que.pop();
	memset(dis,100,sizeof(dis));
	memset(bz,0,sizeof(bz));
	que.push((node){S,dis[S]=0});
	while (!que.empty())
	{
		node now=que.top();que.pop();
		if (bz[now.x])continue;bz[now.x]=1;
		rep(i,now.x)
		{
			if (dis[now.x]+len[i]<dis[tov[i]])
			{
				dis[tov[i]]=dis[now.x]+len[i];
				if (!bz[tov[i]])que.push((node){tov[i],dis[tov[i]]});
			}
		}
	}
}