poj3259 Wormholes 图的负权回路判定,Bellman_Ford

11 篇文章 0 订阅

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

题目大意:空间中有很多点,有一些点之间存在虫洞。给出一些从一个点到另一个点的路,这些路径会花费一个时间(这些路径是双向的),同时给出一些虫洞,通过虫洞从a点到达b点后会倒流一定的时间。问从第一个点出发通过一系列的虫洞和路径回到第一个点后能不能回到过去。

        其实就是判断图中有没有负权回路,标准的Bellman_Ford算法,我就是为了学这个算法才找到这个题目的。要注意的是路径是双向的,而虫洞是单向的。

///2014.7.18
///poj3259

//Accepted  756K    94MS    G++ 1655B   2014-07-19 14:46:42

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

struct Edge{
	int u,v; //起点和终点
	int l; //边长
};
int n,m;   //n是点数,m是边数
const int N=550,M=5500; //问题中给出的可能的最大点数和最大边数(无向边算两条边)
const int MAXL = 0x3f3f3f3f;   //边的无限长
Edge edge[M+10];  //边集
int pre[N+10];    //从源点到该点的路径上该点的前驱
int dist[N+10];   //从源点到该点的最短距离

bool relax( Edge e ){
	if( dist[e.v] > dist[e.u]+e.l ){
		dist[e.v] = dist[e.u]+e.l;
		pre[e.v] = e.u;
		return true;
	}
	return false;
}
bool bellman(int s){
	for(int i=0 ; i<n ; i++){
		dist[i] = MAXL;
		pre[i] = -1;
	}
	dist[s] = 0;
	
	bool change = false;
	for(int i=1 ; i<n ; i++){
		change = false;
		for(int j=0 ; j<m ; j++){
		    if( relax(edge[j]) )
              change = relax;
        }
		if( !change )
		  break;
	}
	
    for(int i=0 ; i<m ; i++){
		if( relax(edge[i]) )
			return false;
	}
	return true;
}

int nn,mm,ww;

void init(){
	scanf("%d%d%d",&nn,&mm,&ww);
	n = nn;
    int a,b,c;
    m = 0;
	for(int i=0 ; i<mm ; i++){
        scanf("%d%d%d",&a,&b,&c);
        a--,b--;
        edge[m].u = a, edge[m].v = b, edge[m].l = c;
        m++;
        edge[m].u = b, edge[m].v = a, edge[m].l = c;
        m++;
    }
    for(int i=0 ; i<ww ; i++){
        scanf("%d%d%d",&a,&b,&c);
        a--,b--;
        edge[m].u = a, edge[m].v = b, edge[m].l = 0-c;
        m++;
    }
}

int main(){
    int t;
    scanf("%d",&t);
    while( t-- ){
        init();

        if( bellman(0) )
          cout<<"NO"<<endl;
        else
          cout<<"YES"<<endl;
    }
    return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值