spfa poj 3259

题意:一个图,有一些“正常”的点和边(废话),点表示农场的位置、边表示从一个农场到另一个农场花费的时间。打住。还有些特别的点(虫洞),这些特别的点和其他点的边代表着能“穿越”的时间。问:有没有可能从虫洞穿越到某个点,时间倒流。

这个模型就是把正常的点互相连接起来或者把正常的点到虫洞,权是正。但是虫洞到其他的点,权为负。建立一个存在负权的图,然后最最最最关键的就是:判断是否存在负权回路。单源最短路算法里面正好bellman-ford可以处理负权,而且算法的返回值就是一个bool型的量,用来反映是不是存在负权回路了

/*
Sample Input

2
3 3 1
1 2 2
1 3 4
2 3 1
3 1 3
3 2 1
1 2 3
2 3 4
3 1 8
Sample Output

NO
YES

*/
#include<cstdio>
#include<vector>
#include<queue>
#include<cstring>

#define MAXVN 520
#define MAXEN 6000
#define INF 1000000000

using namespace std;

int dis[MAXVN], ispushed[MAXVN], pushtimes[MAXVN];

typedef struct{
    int v, value;
}Edge;
int vn, en;

typedef vector<Edge> VE;
VE eg[MAXVN];

queue<int>  Q;

int spfa(int st){
    memset(ispushed, 0, sizeof(ispushed));
    memset(pushtimes, 0, sizeof(pushtimes));
    for(int i = 1;i <= vn; i++)   dis[i] = INF;
    dis[st] = 0;
    while(!Q.empty()) Q.pop();
    Q.push(st); ispushed[st] = 1;
    pushtimes[st]++;
    while(!Q.empty()){
        int be = Q.front();
        Q.pop(); ispushed[be] = 0;
        for(int i = 0; i < eg[be].size(); i++){
            if(dis[eg[be][i].v] > dis[be] + eg[be][i].value){
                dis[eg[be][i].v] = dis[be] + eg[be][i].value;
                if(!ispushed[eg[be][i].v]){
                    Q.push(eg[be][i].v);
                    ispushed[eg[be][i].v] = 1;
                    pushtimes[eg[be][i].v]++;
                    if(pushtimes[eg[be][i].v] >= vn+1)  return 1;
                }
            }
        }
    }

    return 0;
}

int main(){
    int t, n, m, w,a, b, c;
    while(scanf("%d", &t) != EOF){
        while(t--){
            for(int i = 1; i <= vn; i++) eg[i].clear();
            scanf("%d%d%d", &n, &m ,&w);
            vn  =  n;
            while(m--){
                scanf("%d%d%d", &a, &b, &c);
                Edge tmp;
                tmp.v = b;
                tmp.value = c;
                eg[a].push_back(tmp);
                tmp.v = a;
                eg[b].push_back(tmp);

            }
            while(w--){
                scanf("%d%d%d", &a, &b, &c);
                Edge tmp;
                tmp.v = b;
                tmp.value = 0 - c;
                eg[a].push_back(tmp);
            }
            if(spfa(1)) printf("YES\n");
            else printf("NO\n");
        }
    }
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值