Bellman_ford poj 3259

这几天搞差分约束,里面提到Bellman_ford的三角不等式,对Bellman_ford总结一下。。。

Bellman_ford与dijkstra都是求单源多点路径长度。但dijkstra不能带有负权值。关于dijkstra参考:http://blog.csdn.net/bill_ming/article/details/7578037   所以当负权值时就用到了Bellman_ford啦。。。

参考:http://blog.sina.com.cn/s/blog_6803426101014l1v.html

摘自百度百科:http://baike.baidu.com/view/1481053.htm

假设存在最短路径的话,那么我们只要将这条最短路径沿着权值为负的环路在绕一圈,那么这条最短路径的权值就会减少了,所以不存在最短的路径,因为路径的最小值为负无穷

一般形式:

typedef struct Edge
{
    int u,v,w;
} edge[N];
bool Bellman_ford()
{
    //第一步初始化:
    for(int i = 1; i <= n; i++)
        dis[i] = MAX;
    dis[s] = 0;
    //第二步循环求解:
    for(int i = 1; i < n; i++)  // 除源s外 n-1个节点
        for(int j = 1; j <= edgenum; j++)
            if(dis [ edge[j].v ] > dis[ edge[j].u ] + edge[j].w )
            {
                dis [ edge[j].v ] = dis[ edge[j].u ] + edge[j].w;
            }
 //如果某次循环,没有更新源点到任何顶点的dis,那提前结束
    for(int i = 1; i < n; i++)  // 除源s外 n-1个节点
    {
        bool flag = false;
        for(int j = 1; j <= edgenum; j++)
            if(dis [ edge[j].v ] > dis[ edge[j].u ] + edge[j].w )
            {
                dis [ edge[j].v ] = dis[ edge[j].u ] + edge[j].w;
                flag = true;
            }
        if( !flag )
        {
            break;
        }

    }

//第三步:判断是否存在负环

    for(int i = 1; i <= edgenum; i++)
        if(dis[ edge[i].v ] > dis[ edge[i].u ] + edge[i].w )
            return false;
    return true;
}
 


//zhaomingming	3259	Accepted	360K	204MS	C++	1558B	2012-06-03 21:32:02
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int N = 10010;
const int INF = 999999;
struct  Edge
{
    int u;
    int v;
    int t;
} ;
Edge edge[N];
int num;
int n,m,w;
int dis[N] ;
bool Bellman_ford()
{
    for(int i = 1; i <= n; i ++)
    {
        dis[i] = INF;
    }
    bool flag ;
    for(int i = 1; i < n; i++)
    {
        flag = false;
        for(int j = 1; j <= num; j++)
        {
            if(dis[edge[j].v] > dis[edge[j].u] + edge[j].t)
            {
                dis[ edge[j].v ] = dis[edge[j].u] + edge[j].t;
                flag = true;
            }
        }
        if( !flag )
            break;
    }
    for(int j = 1; j <= num; j++)
        if(dis[ edge[j].v ] > dis[edge[j].u] + edge[j].t)
            return true;
    return false;

}
int main()
{
    int F,a,b,c;

    int tt;
    cin >> F;

    while(F--)
    {
        cin >> n >> m >> w;
        num = 0;
        memset(edge,0,sizeof(edge));
        for(int i = 1; i <= m; i++)
        {
            cin >>a >> b >>c;
            num ++;       //无向图
            edge[num].t = c; 
            edge[num].u = a;
            edge[num].v = b;
            num ++;
            edge[num].t = c;
            edge[num].u = b;
            edge[num].v = a;

        }
        for(int i = 1; i <= w; i++)
        {
            cin >> a  >> b >> tt;
            edge[++num].t = -tt;
            edge[num].u = a;
            edge[num].v = b;
        }
        if( Bellman_ford() )
            cout << "YES\n";
        else
            cout << "NO"<<endl;
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值