POJ 3259 Wormholes SPFA算法题解

本题其实也可以使用SPFA算法来求解的,不过就一个关键点,就是当某个顶点入列的次数超过所有顶点的总数的时候,就可以判断是有负环出现了。

SPFA原来也是可以处理负环的。

不过SPFA这种处理负环的方法自然比一般的Bellman Ford算法要慢点了。

#include 
#include 
#include 

const int MAX_N = 501;
const int MAX_M = 2501;
const int MAX_W = 201;

struct Edge
{
	int src, des, wei, next;
	//Edge(int s, int d, int w) : src(s), des(d), wei(w) {}
};

Edge edge[(MAX_M<<1)+MAX_W];
int dist[MAX_N];
int head[MAX_N];
bool vis[MAX_N];
int qu[MAX_N];
int cnt[MAX_N];
int totalEdges;

inline void insertEdge(int src, int des, int wei)
{
	edge[totalEdges].src = src, edge[totalEdges].des = des;
	edge[totalEdges].wei = wei; edge[totalEdges].next = head[src];
	head[src] = totalEdges++;
}

int N, M, W, F;

bool cycleSPFA()
{
	for (int i = 1; i <= N; i++) dist[i] = INT_MAX;
	dist[1] = 0;

	memset(vis, 0, sizeof(bool)*(N+1));
	memset(cnt, 0, sizeof(int)*(N+1));
	int top = 0, tail = 1;	//循环队列的头和尾下标
	qu[top] = 1;
	vis[1] = true;
	cnt[1] = 1;
	while (top < tail)
	{
		int u = qu[top%MAX_N];		//自定义循环队列
		top++;
		vis[u] = false;

		for (int e = head[u]; e ; e = edge[e].next)
		{
			int v = edge[e].des;
			if (dist[u]+edge[e].wei < dist[v])
			{
				dist[v] = dist[u]+edge[e].wei;
				if (!vis[v])
				{
					vis[v] = true;
					qu[tail%MAX_N] = v;
					tail++;
					cnt[v]++;		//记录入列次数
					if (cnt[v] >= N) return true;
				}
			}
		}
	}
	return false;
}

int main()
{
	int src, des, wei;
	scanf("%d", &F);
	while (F--)
	{
		scanf("%d %d %d", &N, &M, &W);
		memset(head, 0, sizeof(int) * (N+1));
		totalEdges = 1;
		for (int i = 0; i < M; i++)
		{
			scanf("%d %d %d", &src, &des, &wei);
			insertEdge(src, des, wei);
			insertEdge(des, src, wei);
		}
		for (int i = 0; i < W; i++)
		{
			scanf("%d %d %d", &src, &des, &wei);
			insertEdge(src, des, -wei);
		}
		if (cycleSPFA()) puts("YES");
		else puts("NO");
	}
	return 0;
}


你可能感兴趣的:(Algorithm算法)