差分约束——AcWing 362. 区间

差分约束

定义

差分约束系统是一种在计算机科学和运筹学中用于解决特定类型优化问题的工具。它主要用于处理一类线性不等式组,这些不等式描述了变量之间的相对大小关系,而不是直接的绝对值大小。差分约束系统通常用于路径寻找、调度、资源分配等问题。

运用情况

  1. 最短路径问题:在有向图中,如果边的权重表示成本或距离,差分约束可以用来找到从一个源点到其他所有点的最短路径。
  2. 任务调度:在任务调度问题中,每个任务可能有完成时间的限制,差分约束可以用来确保任务按照正确的顺序执行,并满足时间限制。
  3. 资源分配:当需要在多个项目之间分配有限资源时,差分约束可以用来确保资源分配的公平性和效率。

注意事项

  • 环路检测:在构建差分约束图时,必须注意避免形成负权环,因为这将导致解决方案不存在或无穷大。
  • 松弛变量:有时,引入松弛变量可以使问题更容易求解,但这也可能增加问题的复杂度。
  • 精度问题:在使用浮点数进行计算时,要注意数值精度可能导致的误差。

解题思路

  1. 构建图模型:将差分约束转换为有向图中的边,其中顶点代表变量,边的权重代表差分约束中的常数。
  2. 应用最短路径算法:利用如贝尔曼-福特算法或迪杰斯特拉算法等最短路径算法来求解。贝尔曼-福特算法尤其适用于存在负权边的情况。
  3. 检查环路:在求解过程中,要检查是否存在负权环,如果有,则说明问题无解。
  4. 解析结果:根据最短路径算法的结果,解析出原始问题的解。

AcWing 362. 区间

题目描述

362. 区间 - AcWing题库

运行代码

#include <cstring>
#include <iostream>

using namespace std;

const int N = 50010, M = N * 3 + 10;

int n;
int h[N], e[M], ne[M], w[M], idx;
int q[N], dist[N];
bool st[N];

void add(int a, int b, int c)
{
    e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx ++ ;
}

void spfa()
{
    memset(dist, -0x3f, sizeof dist);
    q[0] = 0, dist[0] = 0, st[0] = true;
    
    int hh = 0, tt = 1;
    while(hh != tt)
    {
        int t = q[hh ++ ];
        if(hh == N) hh = 0;
        st[t] = false;
        
        for(int i = h[t]; ~i; i = ne[i])
        {
            int j = e[i];
            if(dist[j] < dist[t] + w[i])
            {
                dist[j] = dist[t] + w[i];
                if(!st[j])
                {
                    q[tt ++ ] = j;
                    if(tt == N) tt = 0;
                    st[j] = true;
                }
            }
        }
    }
}

int main()
{
    cin >> n;
    memset(h, -1, sizeof h);
    for(int i = 1; i < N; i ++ )
    {
        add(i, i - 1, -1);
        add(i - 1, i, 0);
    }
    
    for(int i = 0; i < n; i ++ )
    {
        int a, b, c;
        cin >> a >> b >> c;
        a ++, b ++;
        add(a - 1, b, c);
    }
    
    spfa();
    
    cout << dist[50001] << endl;
    
    return 0;
}

代码思路

  • add 函数用于添加图中的边。
  • spfa 函数实现了SPFA算法,用于求解最短路径。
  • q 数组用于队列操作,dist 数组存储当前已知的最短路径长度,st 数组标记节点是否在队列中。
  • 图的邻接表表示:h 存储每个节点的首条边的索引,e 和 w 分别存储边的目的地和权重,ne 存储下一条边的索引。

改进思路

  1. 错误处理:增加对输入的验证,比如检查n是否在合理范围内。
  2. 优化内存使用:如果边的数量远小于最大可能值,可以考虑动态分配边的数组。
  3. 提高读取效率:使用更快的I/O方法,如scanfprintf替代cincout
  4. 边界条件处理:确保spfa函数能够正确处理没有路径到达的情况。
  5. 简化SPFA算法:减少不必要的循环,例如,使用while循环代替两个if语句来处理队列的循环特性。

  • 25
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

筱姌

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值