uva558+uva125

本文介绍了使用Floyd算法解决存在性问题的方法,包括检测负环(UVA 558)和正环(UVA 125)。通过具体的代码实现展示了如何应用Floyd算法进行路径优化,并特别指出在某些情况下Bellman-Ford算法可能更适用。

题意:

两题很像,一个是判断负环是否存在(558),一个是判断正环是否存在(125)

思路:

用floyd,如果形如f[i][i]是正数则有正环,如果是负数,则有负环

注:

558这题用floyd不好,用时太长了,一般用bell-floyd

代码:

uva558:floyd:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn = 2005;
const int inf = 0x3f3f3f3f;
int f,s;
int a, b, c;
int mmap[maxn][maxn];

bool bell() {
	for(int k=0; k<f; k++)
		for(int i=0; i<f; i++)
			for(int j=0; j<f; j++) {
				if(mmap[i][k]!=inf && mmap[k][j]!=inf && mmap[i][j]>(mmap[i][k]+mmap[k][j])) {
					mmap[i][j] = mmap[i][k]+mmap[k][j];
					if(mmap[i][j]<0 &&i==j) return true;

				}
			}
	

	return false;

	
	
}


int main() {
	int cas;
	scanf("%d", &cas);
	while(cas--) {
		scanf("%d%d", &f, &s);
		memset(mmap, inf, sizeof(mmap));

		for(int i=0; i<s; i++) {
			scanf("%d%d%d", &a, &b, &c);
			mmap[a][b] = c;

		}

	if(bell()) printf("possible\n");
	
		else printf("not possible\n");

	}
	return 0;
}
bell:

#include<cstdio>
const int maxn = 2005;
const int INF = 0x3f3f3f3f;
int x[maxn], y[maxn], w[maxn];
int d[1005];
int n, m;
bool bell() {
	for(int i=0; i<n; i++) 
		d[i] = INF;
	d[0] = 0;
	for(int k=0; k<n-1; k++)
		for(int i=0; i<m; i++) {
			int a = x[i], b = y[i];
			if(d[b] > d[a]+w[i] && d[a] != INF) {
				d[b] = d[a] + w[i];
			}
		}
	for(int i=0; i<m; i++) {
		if(d[x[i]] != INF && d[y[i]] > d[x[i]]+w[i])//最短路越来越小
			return true;
	}
	return false;
}
int main() {
	int kase;
	scanf("%d", &kase) ;
	while(kase--) {
		scanf("%d%d", &n, &m);
		for(int i=0; i<m; i++) {
			scanf("%d%d%d", &x[i], &y[i], &w[i]);
		}
		if(bell()) printf("possible\n");
		else printf("not possible\n");
	}
	return 0;
}



uva125:

#include<cstdio>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn = 35;
const int inf = 0x3f3f3f3f;
int f[maxn][maxn];
int n;
int flag;
void floyd() {
	for(int k=0; k<=flag; k++)
		for(int i=0; i<=flag; i++)
			for(int j=0; j<=flag; j++) {
				if(f[i][k] && f[k][j]) f[i][j] += f[i][k]*f[k][j];
			}
	for(int k=0; k<=flag; k++)
		for(int i=0; i<=flag; i++)
			for(int j=0; j<=flag; j++) {
				if(f[k][k] && f[i][k] && f[k][j]) {
					f[i][j] = -1;
				}
			}			

}

int main() {
	int a, b;
	int cas = 0;
	while(scanf("%d", &n) != EOF) {
		flag = 0;
		memset(f, 0, sizeof(f));
		for(int i=0; i<n; i++) {
			scanf("%d%d", &a, &b);
			f[a][b] = 1;
			flag = max(flag, max(a, b));
		}
		floyd();
		printf("matrix for city %d\n", cas++);
		for(int i=0; i<=flag; i++) {
			printf("%d", f[i][0]);
			for(int j=1; j<=flag; j++) {
				printf(" %d", f[i][j]);
			}
			printf("\n");
		}
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值