——by A Code Rabbit
Description
所谓虫洞就是穿过去,可以回到过去!
这种牛逼的东西,大家天马行空开始幻想。
输入一张宇宙图,图中某些边权值为负,即为虫洞。
输出有木有办法不停穿过某些路,无限回到过去!!!
Type
Graph Algorithms
Analysis
求图中权值为负的回路。
可以用深搜,经过的位置标记一下,并且计算自己所处的时间,再次到达某点时,看看是否时间是否更早了,就可以无限回到过去了,很容易理解。
也可以用Bellman-Ford。
因为Bellman-Ford有个性质,某点到某点的路径,最多更新n-1次,可以找到最短路径。
因此如果超过n-1次,路径还在更新的话,即可说明可以无限回到过去了。
// UVaOJ 558 // Wormholes // by A Code Rabbit #include <cstdio> #include <cstring> const int MAXV = 1002; const int MAXE = 2002; const int INF = 1e9; template <typename T> struct Edge { int v; T w; int next; }; template <typename T> struct Graph { Edge<T> edge[MAXE]; int tot_edge; int head[MAXV]; void Init() { tot_edge = 0; memset(head, -1, sizeof(head)); } void AddEdge(int u, int v, T w) { edge[tot_edge].v = v; edge[tot_edge].w = w; edge[tot_edge].next = head[u]; head[u] = tot_edge; tot_edge++; } }; int n, m; int u, v, w; Graph<int> g; int vis[MAXV]; bool exist_circle; void Search(int x, int t); int main() { int tot_case; scanf("%d", &tot_case); while (tot_case--) { scanf("%d%d", &n, &m); g.Init(); for (int i = 0; i < m; ++i) { scanf("%d%d%d", &u, &v, &w); g.AddEdge(u, v, w); } // Solve. for (int i = 0; i < n; ++i) vis[i] = INF; exist_circle = false; Search(0, 0); // Output. printf("%s\n", exist_circle ? "possible" : "not possible"); } return 0; } void Search(int x, int t) { if (exist_circle || t >= vis[x]) return; if (vis[x] != INF) { exist_circle = true; return; } int tmp = vis[x]; vis[x] = t; for (int index = g.head[x]; index != -1; index = g.edge[index].next) { Search(g.edge[index].v, t + g.edge[index].w); } vis[x] = tmp; }
// UVaOJ 558 // Wormholes // by A Code Rabbit #include <cstdio> #include <cstring> const int MAXV = 1002; const int MAXE = 2002; const int INF = 1e9; template <typename T> struct Edge { int u, v; T w; }; template <typename T> struct Graph { Edge<T> edge[MAXE]; int tot_edge; void Init() { tot_edge = 0; } void AddEdge(int u, int v, T w) { edge[tot_edge].u = u; edge[tot_edge].v = v; edge[tot_edge].w = w; tot_edge++; } }; namespace BellmanFord { template <typename T> void Go(Edge<T> e[MAXE], int n, int m, T d[MAXV], int s, bool& exist_circle) { for (int i = 0; i < n; i++) d[i] = i == s ? INF : 0; for (int i = 0; i < n; i++) { bool bo = true; for (int j = 0; j < m; j++) { int u = e[j].u; int v = e[j].v; if (d[u] + e[j].w < d[v]) { d[v] = d[u] + e[j].w; bo = false; } } if (bo) return; } exist_circle = true; } } int n, m; Graph<int> graph; bool exist_circle; int dis[MAXV]; int main() { int tot_case; scanf("%d", &tot_case); while (tot_case--) { // Input. scanf("%d%d", &n, &m); graph.Init(); for (int i = 0; i < m; i++) { int u, v, w; scanf("%d%d%d", &u, &v, &w); graph.AddEdge(u, v, w); } // Solve. exist_circle = false; BellmanFord::Go(graph.edge, n, m, dis, 0, exist_circle); // Output. printf("%s\n", exist_circle ? "possible" : "not possible"); } return 0; }