错了好多次,原因有,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;
}