POJ3169差分约束

差分约束系统
如果一个系统由n个变量和m个约束条件组成,其中每个约束条件形如
xj−xi≤bk (i,j∈[1,n],k∈[1,m])(i,j∈[1,n],k∈[1,m]),则称其为差分约束系统(system of difference constraints)。亦即,差分约束系统是求解关于一组变量的特殊不等式组的方法。

求解差分约束系统,可以转化成图论的单源最短路径(或最长路径)问题。

观察
xj−xi≤bk,会发现它类似最短路中的三角不等d[v]≤d[u]+w[u,v],即d[v]−d[u]≤w[u,v]。因此,以每个变量xi为结点,对于约束条件xj−xi<=bk,连接(i,j),边权为bk。我们再增加一个源点s,s与所有定点相连,边权均为0。对这个图,以s为源点运行Bellman-ford算法(或SPFA算法),最终d[i]即为一组可行解。

#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
#define INF 0x7f7f7f
using namespace std;

const int MAXN = 1000+10;
struct Edge{
    int sta,end,w;
    Edge() = default;
    Edge(int s,int e,int wi){
        sta = s;end = e;w = wi;
    }
};
vector <Edge> edge;
int N,ML,MD;
int Dis[MAXN];

inline void Init(){
    int sta,end,w;
    scanf("%d %d %d",&N,&ML,&MD);
    for(auto i = 0;i < ML;++i){
        scanf("%d %d %d",&sta,&end,&w);
        edge.push_back(Edge(sta,end,w));
    }
    for(auto i = 0;i < MD;++i){
        scanf("%d %d %d",&sta,&end,&w);
        edge.push_back(Edge(end,sta,-w));
    }
    for(auto i = 2;i <= N;++i)       //隐藏的d[i+1] - d[i] >=0
        edge.push_back(Edge(i,i-1,0));
    for(auto i = 1;i <= N;++i)
        if(i == 1)
            Dis[i] = 0;
        else
            Dis[i] = INF;
    return;
}

inline void Bellman_Ford(){
    for(auto k = 0;k < N-1;++k)
        for(auto i = 0;i < edge.size();++i)
            if (Dis[edge[i].end] > Dis[edge[i].sta] + edge[i].w ) {
                Dis[edge[i].end] = Dis[edge[i].sta] + edge[i].w;
            }
    bool flag_nloop = false;
    for(auto i = 0;i < edge.size();++i)  //检查每条边是否还可以优化如果可以就是存在负权回路
        if(Dis[edge[i].end] > Dis[edge[i].sta]+ edge[i].w){
            flag_nloop = true;
            break;
        }
    if(flag_nloop)
        printf("-1\n");
    else if(Dis[N] == INF)
        printf("-2\n");
    else
        printf("%d\n",Dis[N]);
    return;
}

int main()
{
    Init();
    Bellman_Ford();
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值