虫洞:农夫约翰有F个农场,每个农场有N块地,其间有M条路,W条时光隧道(时间倒流)。问是否可能回到过去?
2.5 它们其实都是“图”
最短路
依然很水很基础的 Bellman-Ford 判定负圈,什么都不用考虑,一个 Bellman-Ford 就结束了。
#ifndef ONLINE_JUDGE #pragma warning(disable : 4996) #endif #include <iostream> using namespace std; #define MAX_E (2500 + 200 + 16) * 2 // 从顶点from指向顶点to的权值为cost的边 struct edge { int from, to, cost; edge(){} edge(int from, int to, int cost) { this->from = from; this->to = to; this->cost = cost; } }; // 边 edge es[MAX_E]; // 最短距离 int d[MAX_E]; // V是顶点数,E是边数 int V, E; // 是否存在负圈 bool find_negative_loop() { memset(d, 0, sizeof(d)); for (int i = 0; i < V; ++i) { for (int j = 0; j < E; ++j) { edge e = es[j]; if (d[e.to] > d[e.from] + e.cost) { d[e.to] = d[e.from] + e.cost; // 如果更新了V次,则存在负圈 if (i == V - 1) { return true; } } } } return false; } ///////////////////////////SubMain////////////////////////////////// int main(int argc, char *argv[]) { #ifndef ONLINE_JUDGE freopen("in.txt", "r", stdin); freopen("out.txt", "w", stdout); #endif int F; cin >> F; while (F--) { int N, M, W; cin >> N >> M >> W; V = N; E = 0; for (int i = 0; i < M; ++i) { int from, to, cost; cin >> from >> to >> cost; --from; --to; es[E].from = from; es[E].to = to; es[E].cost = cost; ++E; // 无向图再来一次 es[E].from = to; es[E].to = from; es[E].cost = cost; ++E; } for (int i = 0; i < W; ++i) { int from, to, cost; cin >> from >> to >> cost; --from; --to; es[E].from = from; es[E].to = to; es[E].cost = -cost; ++E; } if (find_negative_loop()) { cout << "YES" << endl; } else { cout << "NO" << endl; } } #ifndef ONLINE_JUDGE fclose(stdin); fclose(stdout); system("out.txt"); #endif return 0; } ///////////////////////////End Sub//////////////////////////////////
lz的答案WA了啊
不对啊,万一有多个连通分量呢。。。
哦,知道了,检查负环的代码和普通的Bellman-Ford有区别