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

来源:互联网 发布:淘宝大c香港站是正品吗 编辑:程序博客网 时间:2024/05/01 12:27

题目链接: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