最短路判负环uva11090

本文介绍使用SPFA算法寻找图中是否存在负权回路的方法,并通过调整边权值进行二分查找确定最小非负权值。代码实现采用C++,适用于解决特定类型的最短路径问题。

这道题注意输出格式是(刘汝佳上的原题不解释。。。)

No circle found.而不是No circle found

还容易出错的地方1.数组大小2.变量的类型(是否会超出变量表示范围)3.边界条件。

此题我觉得是应该有负边但很显然没有相应的测试样咧(我用别人有bug的代码交过。。)

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<queue>
using namespace std;
struct edgee
{
	int to;
	double value;
};
edgee edge[10000];
int nextt[10000], first[500], isinque[500], times[500];
double dist[500];
int edgetot = 0;
int n, m;
void addedge(int a, int b, double c)
{
	edge[edgetot].to = b;
	edge[edgetot].value = c;
	nextt[edgetot] = first[a];
	first[a] = edgetot;
	edgetot++;
}
bool spfa()
{
	queue<int>que;
	for (int i = 1; i <= n; i++) times[i] = 0, isinque[i] = 0, que.push(i), dist[i] = 0;
	while (!que.empty())
	{
		int temp = que.front();
		que.pop();
		isinque[temp] = 0;
		for (int i = first[temp]; i != -1; i = nextt[i])
		{
			int to = edge[i].to;
			if (dist[to] > dist[temp] + edge[i].value)
			{
				dist[to] = dist[temp] + edge[i].value;
				if (!isinque[to])
				{
					isinque[to] = 1;
					que.push(to);
					times[to]++;
					if (times[to]>=n+1)return true;
				}
			}
		}
	}
	return false;
}
bool control(double value)
{
	for (int i = 0; i < edgetot; i++)edge[i].value-= value;
	bool k = spfa();
	for (int i = 0; i < edgetot; i++)edge[i].value += value;
	return k;
}
int main()
{
	int k = 1;
	int t;
	scanf("%d", &t);
	while (t--)
	{
		double l = 999999999, r =-999999999;
		scanf("%d%d", &n, &m);
		for (int i = 1; i < 500; i++)first[i] = -1;
		edgetot = 0;
		for (int i = 0; i < m; i++)
		{
			int a, b; double c;
			scanf("%d%d%lf", &a, &b,&c);
			addedge(a, b, c);
			l = min(l, c);
			r = max(r, c);
		}
		//control(2.5);
		printf("Case #%d: ", k);
		if (!control(r+1))
		{
			printf("No cycle found.\n");
		}
		else
		{
			while (r - l > 1e-4)
			{
				double mid = (l + r) / 2.0;
				bool k=control(mid);
				if (k)
					r = mid;
				else
					l = mid;
			}
			printf("%.2lf\n", l);
		}
		k++;
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值