POJ 3259 Wormholes

题意是判断一个有向图是否存在负环。Bellman Ford算法,先给出一个我没有优化的版本

//212K	204MS
#include <cstdio>
#include <iostream>
#include <cstring>
using namespace std;

const int MAXN = 500;
const int MAXM = 2500;
const int MAXW = 200;
struct edge{
    int from, to;
    int cost;
};
int d[MAXN+5];
edge es[2*MAXM+MAXW+5];
int N, M, W;
int last;

bool judge(){
    memset(d, 0, sizeof(d));
    for(int i=1; i<=N; i++){
        for(int j=1; j<last; j++){
            edge e = es[j];
            if(d[e.to] > d[e.from] + e.cost){
                if(i == N) return 1;
                d[e.to] = d[e.from] + e.cost;
            }
        }
    }
    return 0;
}

int main(){
    int F;
    scanf("%d", &F);
    while(F--){
        scanf("%d%d%d", &N, &M, &W);
        last = 1;
        int s, e, t;
        for(int i=1; i<=M; i++){
            scanf("%d%d%d", &s, &e, &t);
            es[last].from = s; es[last].to = e; es[last].cost = t; last++;
            es[last].from = e; es[last].to = s; es[last].cost = t; last++;
        }
        for(int i=1; i<=W; i++){
            scanf("%d%d%d", &s, &e, &t);
            es[last].from = s; es[last].to = e; es[last].cost = -t; last++;
        }
        if(judge()) puts("YES");
        else puts("NO");
    }
    return 0;
}

双向边只存一次,优化后的代码如下
//184K	125MS
#include <cstdio>
#include <iostream>
#include <cstring>
using namespace std;

const int MAXN = 500;
const int MAXM = 2500;
const int MAXW = 200;
struct edge{
    int from, to;
    int cost;
};
int d[MAXN+5];
edge es[MAXM+MAXW+5];
int N, M, W;
int last;

bool judge(){
    memset(d, 0, sizeof(d));
    for(int i=1; i<=N; i++){
        for(int j=1; j<=M; j++){
            edge e = es[j];
            if(d[e.to] > d[e.from] + e.cost){
                if(i == N) return 1;
                d[e.to] = d[e.from] + e.cost;
            }
            if(d[e.from] > d[e.to] + e.cost){
                if(i == N) return 1;
                d[e.from] = d[e.to] + e.cost;
            }
        }
        for(int j=M+1; j<last; j++){
            edge e = es[j];
            if(d[e.to] > d[e.from] + e.cost){
                if(i == N) return 1;
                d[e.to] = d[e.from] + e.cost;
        }
    }
    }
    return 0;
}

int main(){
    int F;
    scanf("%d", &F);
    while(F--){
        scanf("%d%d%d", &N, &M, &W);
        last = 1;
        int s, e, t;
        for(int i=1; i<=M; i++){
            scanf("%d%d%d", &s, &e, &t);
            es[last].from = s; es[last].to = e; es[last].cost = t; last++;
        }
        for(int i=1; i<=W; i++){
            scanf("%d%d%d", &s, &e, &t);
            es[last].from = s; es[last].to = e; es[last].cost = -t; last++;
        }
        if(judge()) puts("YES");
        else puts("NO");
    }
    return 0;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值