24暑假集训day5上午

图论

差分约束

\(𝑛\) 个整数变量 \(𝑥_1∼𝑥_𝑛\)

给定一些形如 \(𝑥_𝑖+𝑐≥𝑥_𝑗\) 的限制。问有没有可行解,如有输出方案。

例如 \(𝑥_1−1≥𝑥_2,𝑥_2≥𝑥_3,𝑥_3≥𝑥_1\) 就无解。

在单源最短路问题中,如果存在一条 \(𝑖→𝑗\) 长为 \(𝑤\) 的边,在计算 \(1\) 号点到每个点的最短路后,一定有 \(𝑑𝑖𝑠[𝑖]+𝑤≥𝑑𝑖𝑠[𝑗]\)

所以对于每个 \(𝑥_𝑖+𝑐≥𝑥_𝑗\) 的限制,可以连边 \((𝑖,𝑗,𝑐)\)

如果图中存在负环,则无解。假如负环节点编号为 \(1,2,3,…,𝑘\),那么 \(𝑥_1≥𝑥_2−𝑐_{12}≥𝑥_3−𝑐_{12}−𝑐_{23}≥…≥𝑥_1−𝑐_{12}−𝑐_{23}−…−𝑐_{𝑘1}\),而 \(𝑐_{12}+𝑐_{23}+…+𝑐_{𝑘1}<0\),所以无解。

如果图中没有负环,则有解。跑完最短路后,令 \(𝑥_𝑖=𝑑𝑖𝑠[𝑖]\) 即可。

如果有 \(𝑥_𝑖+𝑐=𝑥_𝑗\) 的限制,就拆成 \(𝑥_𝑖+𝑐≥𝑥_𝑗\)\(𝑥_𝑗−𝑐≥𝑥_𝑖\)。所以可以连边 \((𝑖,𝑗,𝑐),(𝑗,𝑖,−𝑐)\)

图不连通时,各个连通块可以独立考虑。

差分约束求值

注意到我们可以给每个 \(𝑥_𝑖\) 都加上一个 \(Δ\),并不影响每个限制 \(𝑥_𝑖+𝑐≥𝑥_𝑗\)。所以无法“求出一组合法解,使得 \(𝑥_𝑝\) 最大 / 最小”。

但是可以“求出一组合法解,使得 \(𝑥_𝑝−𝑥_𝑞\) 最大 / 最小”。

由于 \(𝑥_𝑝−𝑥_𝑞\) 最小 \(⇔𝑥_𝑞−𝑥_𝑝\) 最大,所以我们只考虑让 \(𝑥_𝑝−𝑥_𝑞\) 最大。

由于 \(𝑥_𝑝−𝑥_𝑞≤𝑑𝑖𝑠(𝑞,𝑝)\),所以 \(𝑥_𝑝−𝑥_𝑞\) 再大也不能比 \(𝑑𝑖𝑠(𝑞,𝑝)\) 大。而从 \(𝑞\) 点跑一遍最短路后,\(𝑥_𝑝−𝑥_𝑞\) 正好取到 \(𝑑𝑖𝑠(𝑞,𝑝)\),所以这就是合法的最大值。此时的 \(𝑑𝑖𝑠\) 数组\(𝑑𝑖𝑠[𝑖]=𝑑𝑖𝑠(𝑞,𝑖)\)就是满足 \(𝑥_𝑝−𝑥_𝑞\) 最大时合法的解。

如果有 \(𝑥_𝑖≥𝑤\) 的限制,就连边 \((𝑖,\)起点\(,−𝑤)\),因为 \(𝑑𝑖𝑠[\)起点\(]=0\),所以 \(𝑥_𝑖≥𝑤\) 相当于 \(𝑥_𝑖−𝑤≥𝑥_{起点}=0\)

小K的农场

思路:

\(𝑦_𝑗\) 为农场 \(𝑗\) 的作物单位数。

农场 \(𝑏\) 比农场 \(𝑐\) 至少多种了 ¥𝑑$ 的作物:\(𝑦_𝑏 − 𝑑 ≥ 𝑦_𝑐\),连边 \(𝑏, 𝑐, −𝑑\)

农场 \(𝑏\) 比农场 \(𝑐\) 至多多种了 \(𝑑\) 的作物:\(𝑦_𝑐 + 𝑑 ≥ 𝑦_𝑏\),连边 \(𝑐, 𝑏, 𝑑\)

农场 \(𝑏\) 与农场 \(𝑐\) 种植作物一样多:\(𝑦_𝑏 = 𝑦_𝑐\),连边 \(𝑏, 𝑐, 0\),\(𝑐, 𝑏, 0\)

使用 SPFA 判断图中是否有负环。有负环则无解,无负环则有解。

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<map>
#include<vector>
#include<queue>
#include<set>
#include<unordered_map>
#include<bitset>
#include<climits>
#include<cassert>
using namespace std;
const int MAXN=100005;
int n,m,s,dis[MAXN];
bool inqueue[MAXN];
queue<int> Q;
int flag[MAXN];
vector<pair<int,int> > edges[MAXN];
int main(){int n,m;cin >> n >> m ;memset(dis,0x3f,sizeof(dis));for(int i=0,u,v,w;i<m;i++){int op,a,b,c;cin>>op;if(op==1){cin >> a >> b >> c;edges[a].emplace_back(b,-c);}else if(op==2){cin >> a >> b >> c;edges[b].emplace_back(a,c);}else{cin >> a >> b;edges[a].emplace_back(b,0);edges[b].emplace_back(a,0);}}for(int i=1;i<=n;i++){edges[0].emplace_back(i,0);}dis[s]=0;Q.push(s);inqueue[s]=true;while(!Q.empty()){int x=Q.front();Q.pop();inqueue[x]=false;for(auto edge:edges[x]){if(dis[edge.first]<=dis[x]+edge.second)continue;dis[edge.first]=dis[x]+edge.second;if(!inqueue[edge.first]){Q.push(edge.first);flag[edge.first]=flag[x]+1;if(flag[edge.first]>n){cout<<"No\n";return 0;}inqueue[edge.first]=true;}}}cout<<"Yes\n";return 0;
}

拓扑排序

对于一个有向无环图,为每个节点 \(𝑗\) 分配一个顺序 \(ord_𝑗\),使得对于任意有向边 \(𝑣 → 𝑤\),都有 \(ord_𝑣 < ord_𝑤\)

在有环图上无法做到,假设环为 \(a_1 , a_2 , … , a_𝑛\),则需要 \(ord{a_1} <ord{a_2} < ⋯ < ord{a_𝑚} < ord{a_1}\),矛盾。

最开始的节点一定不能有入度。所以我们可以每次任选一个没有入度的节点,将其拓扑序置为 \(1\)。然后删除此节点,递归处理剩下的图(继续找到没有入度的点,将其拓扑序置为 \(2 ,…\))。

由于删完节点后,图仍然是 DAG,所以存在合法拓扑序。

换句话说,任选一个没有入度的节点都是合法的。

用一个队列维护所有入度 \(=0\) 的点。

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<map>
#include<vector>
#include<queue>
#include<set>
#include<unordered_map>
#include<bitset>
#include<climits>
#include<cassert>
#define int long long
using namespace std;
const int N=100005;inline int read(){int x=0,f=1;char ch=getchar();while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}while (ch>='0'&&ch<='9'){x=x*10+ch-48;ch=getchar();}return x*f;
}
int ord[N], inDegree[N];
int n, m;
queue<int> Q;
vector<int> nextPoints[N];
signed main(){cin >> n >> m;for(int i=0,u, v; i< m; i++){cin >> u >> v;nextPoints[u].push_back(v);inDegree[v]++;}for(int i=0;i<n; i++){if(inDegree[i]==0){Q.push(i);}}int cnt = 0;while(!Q.empty()){int x=Q.front();Q.pop();ord[x] = ++cnt;for(auto y: nextPoints[x]){inDegree[y]--;if(inDegree[y]==0){Q.push(y);}}}return 0;
}

如果原图中存在环,那么这个环以及其能到达的所有点,都不会被删除。

所以可以使用拓扑排序判断有向图是否是 DAG。只需要在结束时判断 \(𝑐𝑛𝑡==𝑛?\) 即可。


两个相似的问题

要求拓扑序靠前的编号尽量小。即最小化 \(𝑜𝑟𝑑^{−1}\) 的字典序。

要求编号小的拓扑序尽量靠前。即最小化 \(𝑜𝑟𝑑\) 的字典序。

其中 \(𝑜𝑟𝑑^(−1)\) 的意思是 \(𝑜𝑟𝑑^{−1} [𝑜𝑟𝑑[𝑖]]=𝑖\),即 \(𝑜𝑟𝑑^{−1}\) \([𝑖]\) 表示拓扑序第 \(𝑖\) 位的节点编号。

拓扑序靠前的编号尽量小

普通的拓扑排序每次任选一个 inDegree=0 的节点。现在我们只需要每次取编号最小的节点即可。

用优先队列替换队列维护 inDegree=0 的节点,每次取出编号最小的节点。

编号小的拓扑序尽量靠前

直接做是不可行的,我们不知道删掉哪个点能最快到达 \(1\) 号点。

但是我们可以让“编号小的拓扑序尽量靠后”:尽量拖延删除 1 号点的时间,直到不得已再删(此时队列中只有 \(1\) 号点)。在此基础上,尽量拖延删除 \(2\) 号点,… 也就是每次删除编号最大的点。

然后反向建图即可。反向的拓扑序靠后就是正向的拓扑序靠前。


拓扑序计数

给定一张有向无环图,求其合法拓扑序个数。

\(𝑛≤20,𝑚≤\frac{𝑛(𝑛−1)}{2}\)

\(𝑓(𝑆)\) 表示 \(𝑆\) 诱导子图的拓扑序个数。

转移时,枚举 \(𝑆\) 中拓扑序最靠前的节点 𝑖 :

\[𝑓(𝑆)=∑_{𝑖∈𝑆,ind_𝑖=0}𝑓(𝑆−\{𝑖\}) \]

其中 ind_𝑖=0 表示 \(𝑖\)\(𝑆\) 中没有入度(而非整个图中)。


次小生成树问题

求次小生成树。(可能与最小生成树边权和相等)

\(𝑛≤1000\)

第三小?


经过 1 号点的最小环

给定一个有向图,无重边无自环,求经过 \(1\) 号点的最小环。

边权非负,\(𝑛,𝑚≤10^5\)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/777276.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

24暑假集训day4上午下午

基础图论 图的存储方式 无向边可以拆成两条有向边 1. 邻接矩阵 邻接矩阵:若 \(𝑖→𝑗\) 存在有向边,则令矩阵 \(𝐴[𝑖][𝑗]=1\)。 遍历一个点的所有出边是 \(𝑂(𝑛)\) 的。 空间复杂度 \(𝑂(𝑛^2 )\)。 总结:复杂度太高,尽量不使用 bool hasEdge[MAXN][M…

微客在线客服系统-连接一切客户

嘿,朋友们,我是微客客服,一个全能的在线客服小能手。今天,我要给大家秀一秀我的超能力——多渠道对接! 想象一下,你的企业就像一个繁忙的交通枢纽,客户咨询就像来来往往的车辆,而我,就是那个指挥交通的智能信号灯。我能帮你把客户咨询引导到正确的地方,让一切沟通都井…

Overleaf中插入pdf图片只显示图片路径的解决方式

最近在用Overleaf写一篇论文,使用IEEE的LaTex模板时发现一个问题,我使用pdfLaTex编译器无法正确显示我插入的pdf图片,网上翻解决方式没有翻到,误打误撞解决了这个问题,问题如下图所示: 即只在图片区域显示路径,不显示图片本身,解决方案是: 在右侧设置里找到编译模式,…

RHCSA 考试试题解析

1.登录测试机初始化 red bule主机 rht-vmctl reset red rht-vmctl reset blue

MySQL的执行计划详解(Explain)(整合版)

目录MySQL的执行计划详解(Explain)(整合版)1、MySQL执行计划的定义2、Explain分析示例3、语法展示4、explain中的列4.1、id4.2、select_type4.3、table4.4、type(重要的)4.5、possible_keys4.6、key4.7、key_len4.8、ref4.9、rows4.10、fitered4.11、Extra MySQL的执行计划详…

ArkTS #01# 组件通信

一、通过Prop单向传递/* * 单双向绑定都有 * 父组件@State,子组件@Link,孙组件@Prop * 数据流向:父组件 <--> 子组件 --> 孙组件*/@Entry @Component export struct BothBinding {@State fatherValue: number = 0//表示组件中的状态变量,这个状态变化会引起 UI 变…

风风影视安装使用

风风影视安装使用教程 一 安装软件下载风风影视 下载好后安装即可。二 配置地址1.点击设置 2.点击配置地址 3.将这串地址复制粘贴,点击确认https://gitee.com/ffddoz/tvbox1/raw/master/fantaiyingff.json到这步就可以使用了以下是功能介绍,非必须看点击主页之后,会有很多选…

idea=services启动类变成灰色了

idea启动大于5个services的时候就会让新启动的变成灰色,并且重启idea之后在services里找不到相关启动类(还要重新翻) 下面版本适用于2023.2.1+(老版本设置页在Advanced Settings中,略有不同) File----->Settings----->Advanced Settings----->Run/Debug,设置完…

常回家看看之tcachebin-attack

常回家看看之tcachebin-attack 自从glibc2.26之后出现了新的堆管理机制,及引用了tcachebin机制,tcachebin也是主要分配小堆块的,有40条bin链(0x10 - 0x410) 那么这样的分配有很多和smallbin 和fastbin重叠的部分,及malloc申请之后free掉的小堆块优先进入tcachebin中,这样…

java 面向对象1

1.java类一个类文件可以定义多个类,只能有一个用public修饰.java基本语法方面在有的很想c++.在学习java面向对象的时候我也得对比c++来学习.学习c++的三大特性:继承,多态,封装,是如何在java中体现的. 2.封装,封装是类最基础的特装类通过将好几个成员数据封装成一个整体,便于数据…