poj3259

错了好多次,原因有,path是双向的,开始没考虑到。边的数组应开到2500*2 + 200。图式不连通的,要把图的各个部分都覆盖到。

本题用spfa算法,判断是否有负权回路。若松弛过程中存在某点的入队次数>=n,则说明有,否则没有。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
using namespace std;

const int maxn = 6000, inf = 100000000;

struct Edge
{
	int v, w, next;
	Edge()
	{
	}
	Edge(int vv, int ww, int nn) :
		v(vv), w(ww), next(nn)
	{
	}
} e[maxn];

int map[maxn], n, m, w;
int dist[maxn];
bool vis[maxn];
int times[maxn];
int q[maxn];

void init()
{
	memset(map, -1, sizeof(map));
	memset(vis, 0, sizeof(vis));
	memset(times, 0, sizeof(times));
	scanf("%d%d%d", &n, &m, &w);
	for (int i = 0; i < n; i++)
		dist[i] = inf;
	for (int i = 0; i < m; i++)
	{
		int a, b, x;
		scanf("%d%d%d", &a, &b, &x);
		a--;
		b--;
		e[i * 2] = Edge(b, x, map[a]);
		map[a] = i * 2;
		e[i * 2 + 1] = Edge(a, x, map[b]);
		map[b] = i * 2 + 1;
	}
	for (int i = m * 2; i < m * 2 + w; i++)
	{
		int a, b, x;
		scanf("%d%d%d", &a, &b, &x);
		a--;
		b--;
		x = -x;
		e[i] = Edge(b, x, map[a]);
		map[a] = i;
	}
}

bool relax(int u, Edge &e)
{
	if (dist[e.v] > dist[u] + e.w)
	{
		dist[e.v] = dist[u] + e.w;
		return true;
	}
	return false;
}

bool spfa(int x)
{
	int front = 0;
	int rear = 1;
	q[front] = x;
	dist[x] = 0;
	vis[x] = true;
	while (front != rear)
	{
		int temp = q[front++];
		if (front == maxn)
			front = 0;
		vis[temp] = false;
		for (int i = map[temp]; i != -1; i = e[i].next)
		{
			if (relax(temp, e[i]) && !vis[e[i].v])
			{
				q[rear++] = e[i].v;
				times[e[i].v]++;
				if (times[e[i].v] > n)
					return true;
				if (rear == maxn)
					rear = 0;
			}
		}
	}
	return false;
}

int main()
{
	//freopen("D:\\t.txt", "r", stdin);
	int t;
	scanf("%d", &t);
	while (t--)
	{
		init();
		bool ok = false;
		for (int i = 0; i < n; i++)
		{
			if (dist[i] == inf)
			if (spfa(i))
			{
				ok = true;
				break;
			}
		}
		if (ok)
			printf("YES\n");
		else
			printf("NO\n");
	}
	return 0;
}
原文地址:https://www.cnblogs.com/rainydays/p/1948671.html