POJ 3259 Wormholes 【Bellman判断是否有负环】

题目链接:http://poj.org/problem?id=3259

题意:从给出的点中任意一个点出发,如果存在一个点能在出发过后回到原点并且所花时间小于0的话就输出YES,否则NO;

一开始看错题目了,以为是从第一个点1出发能不能回到原点(如果英文题不用谷歌翻译,战斗力减半 XD)

Bellman 和Folyd应该都是可以的,我们换一种问法会比较好解题,如果任意一点出发都不能在所花时间小于0的情况下回到原点,就输出NO,那么解法就是判断有没有负环,如果否命题比较容易解就选择否命题的方式写代码;

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>

using namespace std;

const int Maxn = 510;
const int Maxm = 50210;
const int INF = 0x3f3f3f3f;

struct Edge {
    int u,v,w;
} edges[Maxm];

int d[Maxn],E,V,M,worm;

void solve () {
    for (int i = 1; i <= V; ++i) d[i] = INF;
    d[1] = 0; bool check,ok = false;;
    for (int i = 1; i <= V; ++i) {
        for (int j = 1; j <= E; ++j) {
            Edge &e = edges[j];
            if(d[e.u] != INF && d[e.v] > d[e.u]+e.w) {
                if(i == V) ok = true;  // 第V次还能松弛说明有负环
                d[e.v] = d[e.u]+e.w;
                check = true; // 一个小剪枝,如果在V-1之前就没有能松弛的边就直接退出;
            }
        }
        if(!check) break;
    }
    if(ok) printf("YES\n");
    else printf("NO\n");
}


int main (void)
{
    int t,u,v,w;
    scanf("%d",&t);
    while (t--) {
        scanf("%d%d%d",&V,&M,&worm);
        E = 0;
        for (int i = 1; i <= M; ++i) {
            scanf("%d%d%d",&u,&v,&w);
            edges[++E].u = u;
            edges[E].v = v; edges[E].w = w;
            edges[++E].u = v;
            edges[E].v = u; edges[E].w = w;
        }
        for (int i = 1; i <= worm; ++i) {
            scanf("%d%d%d",&u,&v,&w);
            edges[++E].u = u;
            edges[E].v = v;
            edges[E].w = (-1)*w;
        }
        solve ();
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/godleaf/article/details/81558361