其他分享
首页 > 其他分享> > 『笔记』SPFA判断负权环

『笔记』SPFA判断负权环

作者:互联网

基本定义

什么是负权环??

负权环指的是图上的某些边首尾相连构成的,边权和相加小于零的一条环。

例如:

下图中 \(1 \to 2\) \(\to 3\) \(\to 1\) 就是一条负权环,权值和为 \(-1\) 。而 \(2 \to 3\) \(\to 4\) \(\to 5\) 则是一条环而不是负权环,其权值和为 \(10\) 。

性质

显而易见,如果某图存在负权环,那么求最短路的时候如果不特殊处理,那么就会导致程序在负权环上一直转圈圈,所谓的最短路权值和就会越转越小,知道程序优美 \(TLE\) 掉。

基本操作

如何判断负权环呢??

死去的SPFA就是一大利器!!

“请求最短路”:关于____,它____。

“本题存在负环”:关于____,它复活了?!

SPFA BFS型

优缺点

实现思路

代码

bool SPFA_BFS(int st)
{
	q.push(st);
	vis[st] = true;
	while (!q.empty())
	{
		int u = q.front();

		q.pop();
		vis[u] = false;

		for (int i = head[u]; i; i = e[i].nxt)
		{
			int v = e[i].to;

			if (dis[v] > dis[u] + e[i].dis)
			{
				dis[v] = dis[u] + e[i].dis; //最短路松弛

				num[v] = num[u] + 1; //记录某节点出现次数

				if (num[v] >= n) //若大于总节点数,则存在负环
					return true;

				if (!vis[v])
				{
					num[v]++;
					/*
					if(num[v]>=n)
						return true;
					*/
					q.push(v);
					vis[v] = true;
				}
			}
		}
	}
	return false;
}

SPFA DFS型

优缺点

实现思路

代码

bool check(int st)
{
	vis[st] = true;

	for (int i = head[st]; i; i = e[i].nxt)
	{
		int v = e[i].to;

		if (dis[v] > dis[st] + e[i].dis)
		{
			dis[v] = e[i].dis + dis[st];

			if (!vis[v])
			{
				if (SPFA_DFS(v)) //前面搜到了负环
					return true;
			}
			else
				return true; //一次深搜中搜了一个点两次,则存在负环。
		}
	}
	vis[st] = false;

	return false;
}

典型例题

P2850 [USACO06DEC]Wormholes G

#10085. 「一本通 3.3 练习 2」虫洞 Wormholes

温馨提示:珍爱生命,多组数据记得初始化。

标签:true,笔记,st,负环,vis,SPFA,负权,dis
来源: https://www.cnblogs.com/Frather/p/14356999.html