UVaOJ 558 - Wormholes


——by A Code Rabbit


Description

所谓虫洞就是穿过去,可以回到过去!

这种牛逼的东西,大家天马行空开始幻想。

输入一张宇宙图,图中某些边权值为负,即为虫洞。

输出有木有办法不停穿过某些路,无限回到过去!!!


Type

Graph Algorithms


Analysis

求图中权值为负的回路。

可以用深搜,经过的位置标记一下,并且计算自己所处的时间,再次到达某点时,看看是否时间是否更早了,就可以无限回到过去了,很容易理解。

也可以用Bellman-Ford。

因为Bellman-Ford有个性质,某点到某点的路径,最多更新n-1次,可以找到最短路径。

因此如果超过n-1次,路径还在更新的话,即可说明可以无限回到过去了。


Solution
1. DFS
// 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;
}

2. Bellman-Ford
// 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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值