poj-3259

//1408K	266MS	G++
#include <stdio.h>
#include <string.h>

#define FIELD_MAX 504
#define PATH_MAX 5500
#define NO_REACH 9999999

int fieldMap[FIELD_MAX][FIELD_MAX];

struct Path {
	int begin;
	int end;
	int costTime;
};

typedef struct Path Path;
int dis[FIELD_MAX];

Path paths[PATH_MAX];

int N;
int M;
int W;
int realPathNum;

char Bellman_Ford() {
	for (int i = 1; i <= N; i++) {
		dis[i] = NO_REACH;		
	}
	dis[1] = 0; // begin from field 1, in fact, no matter where begin, just check if circular

	for (int i = 2; i <= N; i++) {
		for (int j = 0; j < realPathNum; j++) {
			int from = paths[j].begin; 
			int to = paths[j].end;
			int costTime = paths[j].costTime;
			int relax;
			int original = dis[to];
			if (dis[from] == NO_REACH) {
				relax = NO_REACH;
			} else {
				relax = dis[from] + fieldMap[from][to];
			}
			dis[to] = original < relax ? original : relax;
		}
	}

	for (int j = 0; j < realPathNum; j++) {
		int from = paths[j].begin; 
		int to = paths[j].end;
		int costTime = paths[j].costTime;
		int relax;
		int original = dis[to];
		if (dis[from] == NO_REACH) {
			relax = NO_REACH;
		} else {
			relax = dis[from] + fieldMap[from][to];
		}
		if (original > relax) { // still can relax!
			return 0;
		}
	}
	return 1;
}

void solve() {
	realPathNum = 0;
	for (int i = 1; i <= N; i++) {
		for (int j = 1; j <= N; j++) {
			if (fieldMap[i][j] != NO_REACH) {
				paths[realPathNum].begin = i;
				paths[realPathNum].end = j;
				paths[realPathNum++].costTime = fieldMap[i][j];
				// printf("%d -> %d %d\n",i, j,  fieldMap[i][j]);
			}
		}
	}
	if (Bellman_Ford()) {
		printf("NO\n");
	} else {
		printf("YES\n");
	}
}

int main() {
	int farmNum;
	scanf("%d", &farmNum);
	for (int i = 0; i < farmNum; i++) {
		realPathNum = 0;
		memset(paths, 0, sizeof(paths));
		// memset(fieldMap, 0xff, sizeof(fieldMap));
		for (int i = 0; i < FIELD_MAX; i++) {
			for (int j = 0; j < FIELD_MAX; j++) {
				fieldMap[i][j] = NO_REACH;
			}
		}
		scanf("%d %d %d", &N, &M, &W);
		for (int j = 1; j <= M; j++) {
			int from;
			int to;
			int costTime;
			scanf("%d %d %d", &from, &to, &costTime);
			fieldMap[from][to] = fieldMap[from][to] < costTime ?
			 		fieldMap[from][to]: costTime;
			fieldMap[to][from] = fieldMap[to][from] < costTime ?
			 		fieldMap[to][from]: costTime;
		}
		for (int j = 1; j <= W; j++) {
			int from;
			int to;
			int costTime;
			scanf("%d %d %d", &from, &to, &costTime);
			costTime = -costTime;
			fieldMap[from][to] = fieldMap[from][to] < costTime ?
			 		fieldMap[from][to]: costTime;
		}
		solve();
	}
}

1408K    266MS    G++

基本BF算法应用题,也可以用spfa之类的高速变种,反正只要能检测是否有负环即可。

题目转化难度也不高,读完以后就大概直到是要找负环是否存在。

BF检测到的负环有一个前提: 即此负环应该是从源点可达的,

而题目也没说明具体从哪个点开始,只是要求检测负环罢了,其实这道题最严谨的做法还要找到一个farm中互不联通的点集,(题后面的discuss貌似也有人提出)

比如, 1, 2 ,3 ,4 5

1->2

1->3

3->4

4->5

5->3

3,4,5是一个负环,但是如果从2开始BF,那么因为2不可达3,4,5,因此是检测不到3,4,5负环的。

不过貌似题目暗含了每个field点都是彼此可达的条件,所以就不做这一步了。

然后就好办了,随便从一个点开始做BF算法即可,

有负环就yes了。

还有一点就是,题目说了从一个field到另一个field可能不止一条path,这时候,就要预处理下图,

因为要求负环,因此如果从点A到点B有多条路径,那么要找权值最小的,其他的边可以去掉,不会影响结果。

还要注意,输入的虫洞的costtime要取负。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值