首页 > 其他分享 >浅谈差分约束系统

浅谈差分约束系统

时间:2024-01-24 11:24:07浏览次数:26  
标签:浅谈 int 差分 约束 leq MAXN dis

差分约束系统

前言

真的好久好久都没打过这个算法了。当时学的时候学得不明不白,又不写总结、又不刷题(我都不知道自己咋想的),所以今天刷图论题的时候,发现一车子的差分约束都没打过。

所以,重学,开写!

差分约束系统是什么

不要被他名字的学术性吓到了,这个“系统”字面意思理解就行,不是什么高深庞大的东西。

一个差分约束系统形如:

已知

\[\begin{cases} x_{c_1}-x_{c'_1}\leq y_1 \\x_{c_2}-x_{c'_2} \leq y_2 \\ \cdots\\ x_{c_m} - x_{c'_m}\leq y_m\end{cases} \]

求这个不等式组任意的一组解。

其实说白了,就是 \(n\) 个变量,\(m\) 个约束条件(\(x_i-x_j\leq y_k\))。

怎么解决这个系统

怎么解这个不等式?

首先移项一手:

\[x_i\leq x_j+y_k \]

你看,是不是和图论中的 \(dis_v\leq dis_u+w_i\) 很像啊?

所以这个问题可以转换成一个最短路问题——把 \(j\) 向 \(i\) 连一条权值为 \(y_k\) 的边。

可是这个图并不一定连通,所以我们建一个超级源点 \(0\)。带入到系统中,便是增加了 \(n\) 个约束条件:\(x_i\leq x_0\)。如此,整个系统得到完善。

然后就家常便饭,直接最短路。如果存在负环,不等式组无解;否则可以得到每个点的 \(dis_i\)。而不等式的一组可行解,正是 \(x_i=dis_i\)。

负环怎么判

这里稍微讲一手。

首先为什么出现负环就无解?

因为最短路算法,就是不断走边权最小的边,以更新每个点到源点的最短距离。但如果存在一个环,且总权为负,那么就可以一直走、一直走,直至边权 \(=-\infin\)。

现在,原图共 \(n+1\) 个点,如果不存在负环,那么最短路中每个点肯定只会进队一次。因为没有必要经过两次去松弛它的邻接点。

所以如果 \(n\) 轮松弛结束后仍然存在可松弛的边,那就一定存在负环。

在题目中如何用差分约束算法

如果在模版题,就不多说了。

我们对于题目中的关系,可以得到一些不等条件,再化简成一般形式 \(x_i\leq x_j+y_k\),就可以建立这样一个差分约束系统。

如果是相等情况怎么办?

简单,直接差分成 \(x_i\leq x_j+y_k\) 与 \(x_j\leq x_i+y_k\) 这两条约束条件。

P5960【模板】差分约束

code

#include<bits/stdc++.h>
using namespace std;

#define int long long

const int MAXN=1e4+5;

int n,m;
int dis[MAXN],cnt[MAXN];
bool vis[MAXN];
int su,en[MAXN],lt[MAXN],hd[MAXN],vl[MAXN];

void add(int u,int v,int w)
{
    en[++su]=v,vl[su]=w,lt[su]=hd[u],hd[u]=su;
}

bool SPFA(int s)
{
    queue<int> q;
    memset(dis,0x3f,sizeof(dis));
    vis[s]=1,dis[s]=0;
    q.push(s);
    while (!q.empty())
    {
        int u=q.front();q.pop();
        for(int i=hd[u];i;i=lt[i])
        {
            int v=en[i];
            if(dis[v]>dis[u]+vl[i])
            {
                dis[v]=dis[u]+vl[i];
                if(!vis[v])
                {
                    vis[v]=1,cnt[v]++;
                    if(cnt[v]>n) return 0;
                    q.push(v);
                }
            }
        }
        vis[u]=0;
    }
    return 1;
}

signed main()
{
    scanf("%lld%lld",&n,&m);
    for(int i=1;i<=n;i++)
        add(0,i,0); // 超级源点
    for(int i=1,u,v,w;i<=m;i++)
    {
        scanf("%lld%lld%lld",&u,&v,&w);
        add(v,u,w); // 注意这里是 v --w-> u 
    }
    if(!SPFA(0))
        puts("NO");
    else
    {
        for(int i=1;i<=n;i++)
            printf("%lld ",dis[i]);
    }
    return 0;
}

参考文献

结尾

如果想看图论相关文章,刚好我 2 年前写了一篇。虽然年代久远,格式、文笔也很垃坤,但是得看且看吧。

溜去做题了。

如果你想问为什么有些题目用的差分约束是跑最长路,这个我还不能回答你(我也不知道),但是可以先放张图,等我学会后再回来更(当然也可能忘记了,如果你正在看,可以在评论区踢我)。

图:

(看起来是两种不同的方式罢了……)

标签:浅谈,int,差分,约束,leq,MAXN,dis
From: https://www.cnblogs.com/wang-holmes/p/17984204

相关文章

  • 浅谈智能照明控制系统应用与节能分析
    引言随着人们的物质和精神生活水平不断提高,对生活的追求向着更舒适、安全、高效和节能的方向发展,对建筑照明技术的要求也越来越高。新兴的“智能照明”技术是现代计算机技术、控制技术、通信技术与建筑照明技术的有机结合,与传统照明技术相比在各方面均具有优越性。但是,该技术在实际......
  • CF-1831-E-卡特兰数+异或哈希+差分
    1831-E题目大意给定一个整数\(n\),和\(k\)个区间,区间端点范围在\([1,n]\)内。如果有一个长为\(n\)合法的括号序列,且它的这\(k\)个区间\([l,r]\)中的子括号序列也是合法的,那么称这个括号序列是“好的”。请你求出有多少个长度为\(n\)的“好的”括号序列,答案对\(998244353\)取模......
  • 浅谈 ST 表
    浅谈ST表这种东西还是很简单的,但是涉及左移右移,模板容易打挂,写篇笔记。ST表是什么虽然这个是通过二维数组来实现的,但是我不是很喜欢称之为“表”。我觉得完全可以看作是在一维序列上的区间,看作“表”的话关联性就会很鬼畜。其主要思想是:\(f[i][j]\)表示区间左端点为\(i\)......
  • Go语言核心36讲 09 | 字典的操作和约束
    至今为止,我们讲过的集合类的高级数据类型都属于针对单一元素的容器。它们或用连续存储,或用互存指针的方式收纳元素,这里的每个元素都代表了一个从属某一类型的独立值。我们今天要讲的字典(map)却不同,它能存储的不是单一值的集合,而是键值对的集合。什么是键值对?它是从英文key-va......
  • (坚持每天写算法)算法复习与学习part1基础算法part1-11——差分
    差分和前缀和是有联系的。首先给定一个原数组a:a[1],a[2],a[3],,,,,,a[n];然后我们构造一个数组b:b[1],b[2],b[3],,,,,,b[i];使得a[i]=b[1]+b[2]+b[3]+,,,,,,+b[i]也就是说,a数组是b数组的前缀和数组,反过来我们把b数组叫做a数组的差分数......
  • MySQL-13.MySQL约束
    1.约束(constraint)概述1.1为什么需要约束数据完整性(DataIntegrity)是指数据的精确性(Accuracy)和可靠性(Reliability)。它是防止数据库中存在不符合语义规定的数据和防止因错误信息的输入输出造成的无效操作或错误信息而提出的。为了保证数据的完整性,SQL规范以约束的方式对表数据......
  • 浅谈C++简单前缀和实现
    浅谈前缀和2023.9.28\(tips:\)文章持续更新中,欢迎关注\(upd:\)文章从洛谷博客迁移至博客园(\(2024.1.19\))洛谷B3612【深进1.例1】求区间和题目大E:有一个内部元素个数为\(n\)的数组\(a\),现在有m次询问,求a[l]到a[r]之间所有元素的和朴素的做法:#include<iostream>usin......
  • 【零基础数模系列】模糊分析法、层次分析法和方差分析法
    前言作为数模小白,看了很多讲解新概念新模型的文章,这些文章往往要么讲的很浅不讲原理只讲应用,让人知其然不知其所以然。要么讲的很深小白看不懂,同时总是忽略关键部分,经常性引入陌生概念让初学者疑惑,因此有了本文,任何能熟练掌握线性代数知识且逻辑思维能力尚可的人都可以理解,而无需......
  • 图论——浅谈理论,DFS序和欧拉序
    图论——浅谈理论,DFS序、时间戳和欧拉序提示:本文在树论基础上。下文图例DFS序:124579836.欧拉序:124457997885236631.回加欧拉序:124257975852123631.下文举例均指此图。DFS序周所周知,DFS为深度优先遍历,其框架如:voiddfs(i......
  • #星计划# 浅谈OpenHarmony的NDK开发
    背景NativeAPI(NDK)入门NativeAPI是OpenHarmonySDK上提供的一组native开发接口与工具集合(也称为NDK),方便开发者使用C或者C++语言实现应用的关键功能。NativeAPI只覆盖了OHOS基础的一些底层能力,如libc,图形库,窗口系统,多媒体,压缩库等,并没有完全提供类似于JSAPI上的完整的OHOS平台......