判断负圈的版子题
之前的题用Bellman法判断过了。
这里就用spfa判断一下负圈吧。
用spfa判断负圈的方法有两种:
1.记录节点入队的次数,若次数>n-1则有负圈
2.记录起点到节点经历的边数,若边数>n-1则有负圈(也可以理解为途经的节点数)
第二种会更快一点
代码如下:
#include<iostream>
#include<algorithm>
#include<queue>
#include<cstdio>
using namespace std;
const int max_n = 700;
const int max_m = 3000;
const int inf = 2e9;
struct edge{
int to, cost, next;
}E[max_m << 1];
int head[max_n];
int cnt = 1;
void add(int from, int to, int cost) {
E[cnt].to = to;E[cnt].cost = cost;
E[cnt].next = head[from];head[from] = cnt++;
}
int d[max_n];
int cct[max_n];
bool vis[max_n];
bool spfa(int s,int n) {
fill(d, d + max_n, inf);
fill(cct, cct + max_n, 0);
fill(vis, vis + max_n, false);
queue<int> que;que.push(s);
d[s] = 0;vis[s] = true;
while (!que.empty()) {
int u = que.front();
que.pop();vis[u] = false;
for (int i = head[u];i;i = E[i].next) {
edge& e = E[i];
if (d[e.to] > d[u] + e.cost) {
d[e.to] = d[u] + e.cost;
cct[e.to] = cct[u] + 1;
if (cct[e.to] >= n)return true;
if (vis[e.to])continue;
vis[e.to] = true;
que.push(e.to);
}
}
}return false;
}
int N, M, W;
int main() {
int tcase;scanf("%d", &tcase);
while (tcase--) {
fill(head, head + max_n, 0);cnt = 1;
scanf("%d %d %d", &N, &M, &W);
for (int i = 1, u, v, c;i <= M;++i) {
scanf("%d %d %d", &u, &v, &c);
add(u, v, c);add(v, u, c);
}for (int i = 1, u, v, c;i <= W;++i) {
scanf("%d %d %d", &u, &v, &c);
add(u, v, -c);
}spfa(1, N) ? printf("YES\n") : printf("NO\n");
}
}
京公网安备 11010502036488号