错了好多次,原因有,path是双向的,开始没考虑到。边的数组应开到2500*2 + 200。图式不连通的,要把图的各个部分都覆盖到。
本题用spfa算法,判断是否有负权回路。若松弛过程中存在某点的入队次数>=n,则说明有,否则没有。
#include <iostream> #include <cstdio> #include <cstring> #include <cstdlib> using namespace std; const int maxn = 6000, inf = 100000000; struct Edge { int v, w, next; Edge() { } Edge(int vv, int ww, int nn) : v(vv), w(ww), next(nn) { } } e[maxn]; int map[maxn], n, m, w; int dist[maxn]; bool vis[maxn]; int times[maxn]; int q[maxn]; void init() { memset(map, -1, sizeof(map)); memset(vis, 0, sizeof(vis)); memset(times, 0, sizeof(times)); scanf("%d%d%d", &n, &m, &w); for (int i = 0; i < n; i++) dist[i] = inf; for (int i = 0; i < m; i++) { int a, b, x; scanf("%d%d%d", &a, &b, &x); a--; b--; e[i * 2] = Edge(b, x, map[a]); map[a] = i * 2; e[i * 2 + 1] = Edge(a, x, map[b]); map[b] = i * 2 + 1; } for (int i = m * 2; i < m * 2 + w; i++) { int a, b, x; scanf("%d%d%d", &a, &b, &x); a--; b--; x = -x; e[i] = Edge(b, x, map[a]); map[a] = i; } } bool relax(int u, Edge &e) { if (dist[e.v] > dist[u] + e.w) { dist[e.v] = dist[u] + e.w; return true; } return false; } bool spfa(int x) { int front = 0; int rear = 1; q[front] = x; dist[x] = 0; vis[x] = true; while (front != rear) { int temp = q[front++]; if (front == maxn) front = 0; vis[temp] = false; for (int i = map[temp]; i != -1; i = e[i].next) { if (relax(temp, e[i]) && !vis[e[i].v]) { q[rear++] = e[i].v; times[e[i].v]++; if (times[e[i].v] > n) return true; if (rear == maxn) rear = 0; } } } return false; } int main() { //freopen("D:\\t.txt", "r", stdin); int t; scanf("%d", &t); while (t--) { init(); bool ok = false; for (int i = 0; i < n; i++) { if (dist[i] == inf) if (spfa(i)) { ok = true; break; } } if (ok) printf("YES\n"); else printf("NO\n"); } return 0; }