SPFAはリング裸のタイトルを失います。
メインリングSPFA陰性分析\(2 \)メソッドを:
- 各点がよりデキュー以上の数に等しいかどうかを決定する(N \)\。
- より大きいの各点上の点の数かどうかを決定又は最短経路に等しく\(\ N-) 。
どちらの方法は、十分に文書化されています。私は個人的に第二の方法を使用することをお勧めします。
そこで、我々はちょうどSPFAの過程で最短経路上の各点の点の数にそれを記録します。
だから我々は、キューにすべてのポイントを開始しますので\(DIST \)の配列に初期化する必要があります(0 \)\。
#include <bits/stdc++.h>
using namespace std;
const int N = 503, M = 5203;
int n, m, f, w;
int tot, head[N], ver[M], edge[M], nxt[M];
int dist[N], cnt[N];
bool st[N];
inline void add(int u, int v, int w)
{
ver[++tot] = v, edge[tot] = w, nxt[tot] = head[u], head[u] = tot;
}
inline bool SPFA()
{
memset(dist, 0, sizeof dist);
memset(cnt, 0, sizeof cnt);
memset(st, false, sizeof st);
queue <int> q;
for (int i = 1; i <= n; i+=1)
{
q.push(i); //一开始先将所有的点加入队列
st[i] = true;
}
while (!q.empty())
{
int u = q.front(); q.pop();
st[u] = false;
for (int i = head[u]; i; i = nxt[i])
{
int v = ver[i], w = edge[i];
if (dist[v] > dist[u] + w)
{
dist[v] = dist[u] + w;
cnt[v] = cnt[u] + 1; //记录每个点最短路经的条数
if (cnt[v] >= n) return true; //存在负环
if (!st[v])
{
st[v] = true;
q.push(v);
}
}
}
}
return false;
}
int main()
{
cin >> f;
while (f--)
{
cin >> n >> m >> w;
memset(head, 0, sizeof head);
tot = 0;
for (int i = 1; i <= m; i+=1)
{
int u, v, w;
cin >> u >> v >> w;
add(u, v, w), add(v, u, w);
}
for (int i = 1; i <= w; i+=1)
{
int u, v, w;
cin >> u >> v >> w;
add(u, v, -w);
}
if (SPFA()) puts("YES");
else puts("NO");
}
return 0;
}