SPFA和dijkstra优化

SPFA

  • 单源最短路,好哇

  • 时间复杂度玄

  • 无畏负权边,容易被卡负环

  • 好打好理解

  • S L F SLF SLF优化:如果当前要入队一个点 i i i,如果 d i s [ i ] < d i s [ q u e [ h e a d ] ] dis[i] < dis[que[head]] dis[i]<dis[que[head]] (比队首要优)就放入队首,否则就放入队尾

  • L L L LLL LLL优化:如果当前的出队的数( q u e [ h e a d ] que[head] que[head]),他的 d i s dis dis大于队列中所有 d i s dis dis的平均值,那么就把 q u e [ h e a d ] que[head] que[head]入队尾,然后 c o n t i n u e continue continue

  • 可以用 S T L STL STL d e q u e deque deque来实现 S L F SLF SLF L L L LLL 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+m)log2n),很多题目一般可以看成 O ( n l o g 2 n ) O(nlog_2n) O(nlog2n)乘上个 3 3 3左右的常数

  • 只要没有负权边就强大通用

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

  • 堆优化完比 S P F A SPFA 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]]});
			}
		}
	}
}

你可能感兴趣的:(图论,最短路)