题目链接: POJ 3259 Wormholes
题目大意:
一个图,有正权值的双向边和负权值的单项边,判断是否有负环。
题解:
SPFA的模板直接套用即可。
代码:
#include <iostream>
#include <queue>
#include <vector>
#include <list>
#define INF 0x3f3f3f3f
#define MAXN 510
using namespace std;
typedef pair<int, int> P;
vector<P> adj[MAXN];
vector<int> dist(MAXN, INF);
int F, N, M, W;
bool find_negative_loop(int s) {
list<int> que;
vector<int> cnt(N+1, 0);
vector<bool> flag(N+1, false);
que.push_back(s);
dist[s] = 0;
cnt[s] = 1;
flag[s] = false;
while (!que.empty()) {
int u = que.front();
que.pop_front();
flag[u] = false;
for (int i = 0; i < adj[u].size(); i++) {
int v = adj[u][i].first;
int w = adj[u][i].second;
if (dist[v] > dist[u] + w) {
dist[v] = dist[u] + w;
if (!flag[v]) {
if (N == ++cnt[v]) return true;//判断有负环
if (!que.empty() && dist[v] < dist[que.front()])
que.push_front(v);
else que.push_back(v);
flag[v] = true;
}
}
}
}
return false;
}
int main() {
ios::sync_with_stdio(false);
cin >> F;
for (int case_n = 1; case_n <= F; case_n++) {
cin >> N >> M >> W;
for(int i = 0; i < MAXN; i++) {
adj[i].clear();
dist[i] = INF;
}
//输入正权值双向边
for (int i = 0; i < M; i++) {
int u, v, w;
cin >> u >> v >> w;
//双向边可以用两个单向边代替
adj[u].push_back(make_pair(v, w));
adj[v].push_back(make_pair(u, w));
}
//输入负权值单项边
for (int i = 0; i < W; i++) {
int u, v, w;
cin >> u >> v >> w;
adj[u].push_back(make_pair(v, -w));
}
if (find_negative_loop(1))
cout << "YES" << endl;
else cout << "NO" << endl;
}
return 0;
}