ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

poj3169:Layout——差分约束+Bellman-Ford算法

2022-02-16 11:04:31  阅读:237  来源: 互联网

标签:BD dist AD int DD Bellman Ford BL Layout


差分约束系统

参考:https://www.cnblogs.com/genius777/p/9163103.html

差分约束系统只是对最短路算法的一种应用,没有什么新的算法,只是对于具体问题的建图方法的确定

差分约束系统解决的问题是不等式组的求解:

X1 - X2 <= 0
X1 - X5 <= -1
X2 - X5 <= 1
X3 - X1 <= 5
X4 - X1 <= 4
X4 - X3 <= -1
X5 - X3 <= -3
X5 - X4 <= -3

这就是一个不等式组,给出的不等式组只存在小于等于号,如果有个别的式子是大于等于,我们可以通过两边同时乘-1的得到统一的不等号方向的不等式组。

这个不等式组一定是无解和无数解两种情况,因为如果是存在任意一组解,{x1,x2,x3,x4,x5},我们都可以通过{x1+k,x2+k,x3+k,x4+k,x5+k}得到一个新的解。所以解的个数是无数的。

因为每个数都加k,他们任意两个数之间的差是不变的,所以对于不等式没有影响。

与最短路联系

B - A <= c     (1)
C - B <= a     (2)
C - A <= b     (3)

如果要求C-A的最大值,可以知道max(C-A)= min(b,a+c),而这正对应了下图中C到A的最短路。

img

差分约束建图技巧

1.对于一个全部都是<=号的不等式组,我们可以将每个式子转化为Xi<=Xj+W(i,j),那么就建一条边,Xj->Xi=W(i,j),然后利用最短路径解决问题,在x0定死的情况下,求得最小值

2.对于一个全部都是>=号的不等式组,我们可以将每个式子转化为Xi>=Xj+W(i,j),那么就建一条边,Xj->Xi=W(i,j),然后利用最长路径解决问题,在x0定死的情况下,求得最大值

如果dis[Xi]为inf或-inf,那么Xi为任意解

如果求最短路的过程中出现负环,那么说明该不等式组无解

题目描述

需要放置n头牛,AL和BL两头牛之间存在“喜欢”关系,则它们之间的距离不能超过DL,有些AD和BD两头牛之间存在“不喜欢”关系,则它们之间的距离不能超过DD。所有牛编号从1~N,求1号牛和N号牛之间的最大距离,无解输出-1,距离无限大输出-2

分析

根据条目分析,可以得出约束条件为,d[i]为第i头牛放置的位置

  • d[i+1] + 0 >= d[i],n头牛按编号顺序依次放置,且可放置在同一位置
  • d[AL] + DL >= d[BL],“喜欢”关系的两头牛之间距离不超过DL
  • d[BD] - DD >= d[AD],“不喜欢”关系两头牛之间的距离不小于DD

将原问题转化成最短路问题,

  • 建立一条从i+1到i,权值为0的边
  • 建立一条从AL到BL,权值为DL的边
  • 建立一条从BD到AD,权值为-DD的边

原问题d[N] - d[1]的最大值,对应顶点1到顶点N的最短距离(不理解可看上文差分约束与最短路径关系部分),由于图中存在负权重的边,不能使用Dijkstra算法,可采用Bellman-Ford算法求解。

代码

#include <stdio.h>
#include <iostream>
#include <climits>
#include <vector>
using namespace std;

const int MAXN = 1000 + 10;
const int MAXM = 10000 + 10;
const int INF = INT_MAX;

int N, ML, MD;
int AL[MAXM], BL[MAXM], DL[MAXM];   //'喜欢'关系约束
int AD[MAXM], BD[MAXM], DD[MAXM];   //'不喜欢'关系约束
int dist[MAXN];     //最短距离

//邻接表存储图
struct Edge{
    int to, weight;
    Edge(int t, int w): to(t), weight(w) {}
};
vector<Edge> G[MAXN];

//根据差分约束建立图
void BuildGraph(){
    //从i+1->i权值为0的边
    for (int i = 1; i < N; ++i) {
        G[i+1].push_back(Edge(i, 0));
    }

    /*
         * BL - AL <= DL
         * AL + DL >= BL
         * 从AL到BL权值为DL的边 */
    for (int i = 0; i < ML; ++i) {
        G[AL[i]].push_back(Edge(BL[i], DL[i]));
    }

    /*
         * BD - AD >= DD
         * BD - DD >= AD
         * 从BD到AD权值-DD的边*/
    for (int i = 0; i < MD; ++i) {
        G[BD[i]].push_back(Edge(AD[i], -DD[i]));
    }
}

void Bellman_Ford(){
    fill(dist, dist + MAXN, INF);
    dist[1] = 0;

    //循环N-1次
    for (int i = 0; i < N - 1; ++i) {
        //对所有边进行松弛操作
        for (int j = 1; j <= N; ++j) {
            for (int k = 0; k < G[j].size(); ++k) {
                Edge e = G[j][k];
                if (dist[j] < INF && dist[e.to] > dist[j] + e.weight){
                    dist[e.to] = dist[j] + e.weight;
                }
            }
        }
    }

    //再遍历一次所有边(第N次循环)
    bool ngloop = false;
    for (int j = 1; j <= N; ++j) {
        for (int k = 0; k < G[j].size(); ++k) {
            Edge e = G[j][k];
            //如果本次有更新,则存在负环
            if (dist[j] < INF && dist[e.to] > dist[j] + e.weight){
                dist[e.to] = dist[j] + e.weight;
                ngloop = true;
            }
        }
    }

    if (ngloop){
        printf("-1\n");
    }
    else{
        int ans = dist[N];
        if (ans == INF){
            ans = -2;
        }
        printf("%d\n", ans);
    }
}

int main(){
    scanf("%d%d%d", &N, &ML, &MD);
    for (int i = 0; i < ML; ++i) {
        scanf("%d%d%d", &AL[i], &BL[i], &DL[i]);
    }
    for (int i = 0; i < MD; ++i) {
        scanf("%d%d%d", &AD[i], &BD[i], &DD[i]);
    }

    BuildGraph();

    Bellman_Ford();

    return 0;
}

标签:BD,dist,AD,int,DD,Bellman,Ford,BL,Layout
来源: https://www.cnblogs.com/dctwan/p/15899500.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有