POJ3259 Wormholes

本文提供两种检测图中是否存在负权回路的方法:Bellman-Ford算法与Floyd-Warshall算法。通过实例演示了如何使用这两种算法,并提供了完整的C++代码实现。

题目来源:http://poj.org/problem?id=3259

第一个是Bellman-Ford  、第二个是Floyd-Warshall。


(一)

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

struct edge{
    int from,to,cost;
}ed[6005];
int F,N,M,W;
int d[505],num;

bool find_negative_loop();
int main()
{
    cin>>F;
    while(F--){
        scanf("%d%d%d",&N,&M,&W);
        int s,e,t;
        num=0;
        for(int i=1;i<=M;i++){
            scanf("%d%d%d",&s,&e,&t);
            ed[num].from=s;ed[num].to=e;ed[num].cost=t;
            num++;
            ed[num].from=e;ed[num].to=s;ed[num].cost=t;
            num++;
        }
        for(int i=1;i<=W;i++){
            scanf("%d%d%d",&s,&e,&t);
            ed[num].from=s;ed[num].to=e;ed[num].cost=-t;
            num++;
        }
        if(find_negative_loop()) cout<<"YES\n";
        else cout<<"NO\n";
    }
    return 0;
}
//Bellman-Ford
bool find_negative_loop(){
    memset(d,0,sizeof(d));
    for(int i=1;i<=N;i++){
        for(int j=0;j<num;j++){
            edge e=ed[j];
            if(d[e.to]>d[e.from]+e.cost){
                d[e.to]=d[e.from]+e.cost;
                //如果不存在负圈,最短路不会经过一个顶点两次,故i最多执行N-1次。
                if(i==N) return 1;
            }
        }
    }
    return 0;
}
(二)

/*
1
3 3 1
1 2 1
2 1 3
2 3 1
3 1 3
*/
#include <iostream>
#include<cstdio>
#include<cstring>
using namespace std;

int d[505][505];
int F,N,M,W;

bool find_negative_loop();
int main()
{
    cin>>F;
    while(F--){
        scanf("%d%d%d",&N,&M,&W);
        memset(d,0x3f3f3f3f,sizeof(d));
        for(int i=1;i<=N;i++)
            d[i][i]=0;
        int s,e,t;
        for(int i=0;i<M;i++){
            scanf("%d%d%d",&s,&e,&t);
            //这里最易出错:(1)双向边(2)不能直接覆盖之前的值
            //d[s][e]=d[e][s]=t;
            if(t<d[s][e]) d[s][e]=d[e][s]=t;
        }
        for(int i=0;i<W;i++){
            scanf("%d%d%d",&s,&e,&t);;
            d[s][e]=-t;
        }
        if(find_negative_loop()) cout<<"YES\n";
        else cout<<"NO\n";

    }
    return 0;
}
//Warshall-floyd
bool find_negative_loop(){

    for(int k=1;k<=N;k++){
            for(int i=1;i<=N;i++){
                for(int j=1;j<=N;j++){
                    if(d[i][k]+d[k][j]<d[i][j]) d[i][j]=d[i][k]+d[k][j];
                    //d[i][j]=(d[i][j]<d[i][k]+d[k][j]?d[i][j]:d[i][k]+d[k][j]);
                }
                if(d[i][i]<0) return 1;
            }
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值