题目链接:http://poj.org/problem?id=3259。
思路:判断Farmer John能否通过虫洞穿越过去见到自己,问题可以转化为判断给定有权图是否存在负权圈,使用Bellman-Ford算法可以判断,代码实现如下:
#include <iostream>
#include <cstring>
#include <vector>
using namespace std;
const int maxn = 0xfffffff, maxq = 300000, maxd = 505;
struct node
{
int to, dist;
node(int to, int dist) : to(to), dist(dist) {}
};
int q[maxq], first, last, cnt[maxd], dist[maxd];
bool inq[maxd], success;
vector<node> graph[maxd];
int num, n, m, w;
void Bellmen_ford(int start) {
dist[start] = 0;
q[++last] = start;
inq[start] = true;
while (first < last) {
int index = q[++first];
inq[index] = false;
for (int i = 0; i < graph[index].size(); i++) {
int v = graph[index][i].to;
if (dist[v] > dist[index]+graph[index][i].dist) {
dist[v] = dist[index]+graph[index][i].dist;
cnt[v]++;
if (cnt[v] >= n) {
success = true;
break;
}
if (!inq[v]) {
inq[v] = true;
q[++last] = v;
}
}
}
if (success) break;
}
if (success) cout << "YES" << endl;
else cout << "NO" << endl;
}
int main() {
cin >> num;
while (num--) {
cin >> n >> m >> w;
first = last = -1;
success = false;
memset(cnt, 0, sizeof(cnt));
memset(inq, false, sizeof(inq));
for (int i = 1; i <= n; i++) {
graph[i].clear();
dist[i] = maxn;
}
for (int i = 0; i < m; i++) {
int s, e, d;
cin >> s >> e >> d;
graph[s].push_back(node(e, d));
graph[e].push_back(node(s, d));
}
for (int i = 0; i < w; i++) {
int s, e, d;
bool exsit = false;
cin >> s >> e >> d;
for (int j = 0; j < graph[s].size(); j++) {
if (graph[s][j].to == e) {
graph[s][j].dist = 0-d;
exsit = true;
break;
}
}
if (!exsit) {
graph[s].push_back(node(e, 0-d));
}
}
Bellmen_ford(1);
}
return 0;
}
还可以使用Floyd进行判断,在每次更新后只需检查graph[i][i]是否小于0即可,如果小于0就说明存在负权环。代码如下:
#include <iostream>
#include <vector>
#include <cstring>
#include <cstdio>
using namespace std;
const int maxn = 505, maxDis = 0x3f3f3f3f;
int graph[maxn][maxn], n, m, w, s, e, t;
bool Floyd() {
int i, j, k, t;
for (k = 1; k <= n; k++) {
for (i = 1; i <= n; i++) {
for (j = 1; j <= n; j++) {
t = graph[i][k] + graph[k][j];
if (t < graph[i][j]) graph[i][j] = t;
}
if (graph[i][i] < 0) return true;//check
}
}
return false;
}
int main() {
int F;
cin >> F;
while (F--) {
//init
memset(graph, maxDis, sizeof(graph));
cin >> n >> m >> w;
for (int i = 1; i <= n; i++) graph[i][i] = 0;
for (int i = 0; i < m; i++) {
cin >> s >> e >> t;
if (t < graph[s][e]) graph[s][e] = graph[e][s] = t;
}
for (int i = 0; i < w; i++) {
cin >> s >> e >> t;
graph[s][e] = -t;
}
bool hasNegCycle = Floyd();
if (hasNegCycle) cout << "YES" << endl;
else cout << "NO" << endl;
}
return 0;
}