//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要取负。