农夫要回到原点,找一条负权环,注意输入有正权双向路径和负权单向路径。 #include <iostream> #include <cstdio> #include <cstring> using namespace std; int all = 0; //有向边数 int dis[501]; //源点到各点权值 int N, M, W; // N点数,M正权双向边数,W负权单向边数 class weight { public: int s; int e; int t; } edge[5200]; bool bellman_ford() { bool flag; for (int i = 1; i <= N-1; ++i) { flag = false; for (int j = 0; j < all; ++j) { if (dis[edge[j].s] + edge[j].t < dis[edge[j].e]) { dis[edge[j].e] = dis[edge[j].s] + edge[j].t; flag = true; } } if (!flag) break; } //这里没有对dis[源]初始化,是因为当满足下面条件时,也会出现负权环 for (int i = 0; i < all; ++i) if (dis[edge[i].s] + edge[i].t < dis[edge[i].e]) return true; // 存在负权环 return false; } int main() { //freopen("temp.txt", "r", stdin); int F; cin >> F; while (F--) { memset(dis, 1, sizeof(dis)); // memset是对每个字节赋值,这里要求>10000, 大约为2^24 cin >> N >> M >> W; all = 0; int S, E, T; // 源点,目的点,所需时间 for (int i = 0; i < M; ++i) { cin >> S >> E >> T; edge[all].s = edge[all+1].e = S; edge[all].e = edge[all+1].s = E; edge[all++].t = T; edge[all++].t = T; } for (int i = 0; i < W; ++i) { cin >> S >> E >> T; edge[all].s = S; edge[all].e = E; edge[all++].t = -T; // 注意是负权 } if (bellman_ford()) cout << "YES" << endl; else cout << "NO" << endl; } return 0; }