——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;
}