二分图与网络流,ACMer需要掌握的一些模型

news/2024/6/30 17:49:00/文章来源:https://www.cnblogs.com/maple276/p/18272405

写在前面

前些日子的四川省赛,我们队伍拿到了网络流C题的一血。看完题目和队友讨论了下,大概两三分钟就把题目正确做法讨论出来了,但是写代码过程还是比较笨拙的,建完图后一度蒙圈甚至不知道自己建的是什么意思,后来冷静下来才把图改对。

作为23年学校图论专题的负责人,我觉得自己的网络流水平还是需要锻炼下。最近也是24暑假前集训收官了,把今年的图论专题网络流题目和以前做过的题目一起总结下。

我一直觉得,网络流题一是靠经验,二是靠一些熟悉的模型,如果模型套对了,就可以享受快速过题甚至拿一血的乐趣。

这篇随笔大概会涉及以下内容:二分图匹配、最小点覆盖、最大独立集;最小割残余网络的处理、方案的输出、切糕模型;最大权闭合子图;方阵上的一些网络流模型;DAG转二分图的模型;

讲述比较随意,可能以后还会更新。

二分图相关

二分图匹配:

点数较少的时候可以使用 \(O(nm)\) 的匈牙利算法,比较好写。

其余情况可以无脑网络流,dinic 算法跑二分图的复杂度约为 \(O(m\sqrt n)\),详见 ICPC2023济南E。

最大权值匹配可以费用流,但最大费用最大流不一定是最大费用流(如下图),为了让其强制最大流,可以从每个左部结点向汇点连一条费用为 0,流量为 1 的边。这个补流的思想还是比较有用的,下面会涉及到。

最小点覆盖

最小点覆盖的含义:选出图中的一些点,满足图中所有边的两端至少有一个点被选中,最小的点集即为最小点覆盖。

在二分图中,最大匹配的数量和最小点覆盖的点数是相同的。如果你将某题的题意转化为了求二分图的最小点覆盖,那么直接跑最大流就是答案。

在一般图中,最大匹配的数量和最小点覆盖的点数不一定相同,比如最简单的一个三角形图,最大匹配为1,最小点覆盖却是2。

一般图最大匹配有多项式复杂度的带花树,而一般图最小点覆盖是npc。

我们知道最大匹配的方案很好输出,匈牙利算法自动匹配好了,最大流只需要看看残余网络的情况。但最小点覆盖的方案就要稍微难找一些,Matrix67大佬的博客里有König定理的证明以及求出一组方案的过程,我们可以利用这个定理进行方案查找:二分图最大匹配的König定理及其证明

下面是匈牙利算法求最小点覆盖的代码:

#include <bits/stdc++.h>
#define ll long longusing namespace std;
const int N=1010;inline int read() {int sum = 0, ff = 1; char c = getchar();while(c<'0' || c>'9') { if(c=='-') ff = -1; c = getchar(); }while(c>='0'&&c<='9') { sum = sum * 10 + c - '0'; c = getchar(); }return sum * ff;
}int n1,n2,m;
vector <int> e[N];
int vis[N],belong[N];  // index is the right_part of G(V,E)
bool tagx[N],tagy[N];int DFS(int u) {for(int v : e[u]) {if(vis[v]) continue;vis[v] = 1;if(!belong[v] || DFS(belong[v])) { belong[v] = u; return 1; }}return 0;
}void mark(int u) {if(tagx[u]) return ;tagx[u] = 1;for(int v : e[u]) {if(!tagy[v] && belong[v]) {tagy[v] = 1;mark(belong[v]);}}
}int main() {int x,y;n1 = read(); n2 = read(); m = read();while(m--) {x = read(); y = read();e[x].push_back(y);}int ans = 0;for(int i=1;i<=n1;i++) {memset(vis, 0, sizeof(vis));ans += DFS(i);}cout<<"ans = "<<ans<<endl;memset(vis, 0, sizeof(vis));for(int i=1;i<=n2;i++) vis[ belong[i] ] = 1;for(int i=1;i<=n1;i++) if(!vis[i]) mark(i);for(int i=1;i<=n1;i++) if(!tagx[i]) cout<<i<<" ";cout<<endl;for(int i=1;i<=n2;i++) if(tagy[i]) cout<<i<<" ";cout<<endl;return 0;
}/*4 4 7
1 1
2 2
1 3
2 3
2 4
3 2
4 2*/

其实除了König定理,直接在网络流的残余网络里进行DFS也可以求出最小点覆盖的方案,其过程与König定理的原理相似。

这个会在下一个大标题里讲。

最大独立集

最大独立集的含义是:选出图中的一些点,满足图中不存在两个端点都被选中的边,最大的点集即为最大独立集。

无论是在二分图还是一般图当中,最大独立集和最小点覆盖永远是互补的关系,两者相加即为点数。证明非常简单,思考个四五秒就懂了。

也就是说,二分图的最大独立集 = 总点数 - 最小点覆盖 = 总点数 - 最大匹配。想要求二分图最大独立集点数,只需让总点数(两边点数和)减去最大流。

若要求出一组方案,那和求最小点覆盖的方法是完全相同的,因为它就是最小点覆盖的补集。

如果你可以将题目按照以下步骤转化:

1、转化为二分图,将点分成两边阵营。

2、两边阵营某些关系存在冲突(两者只能选其一),给两个点连一条边。

3、要求最大可以保留的点数。

那就是最大独立集的模型了,答案是总点数减去最小割。可以减少些思考时间。

最小割的残余网络

输出最小割方案

首先总所周知,残余网络上流量为0的边,并不代表它被割掉了。因为一条增广路可能会让很多边的流量变为0,但我们只需要割一条边。

如果题目需要我们给出一组最小割的方案(例如2021 ECfinal H),我们到底应该割掉哪些边呢?


其实这是一个与最小割定义相关的问题。

最小割的定义是,将所有点划分为 S 和 T 两个集合,满足源点在 S 中,汇点在 T 中,且所有从 S 到 T 的边流量之和最小。那么,从 S 到 T 的所有边,就是我们要割掉的边。

我们跑完最大流后,为什么找不到新的增广路了,就是因为 S 到 T 的所有边都被割掉了。

如果我们从源点进行DFS,每次只沿着流量不为0的边走,我们走到的所有点的集合其实就是点集 S 的一种方案。

下图图一,浅蓝色边为增广路,红色为最小割的方案,虽然源点到第一个点的边流量也变成了0,但是它不能是最小割的边。

下图图二,深蓝色边是跑完最大流后的残余网络,我们从源点开始DFS,绿色点即为 S 中的点,其余点为 T 中的点。在最小割的方案:左部点中未被绿色标记的点,是边被割去的点,右部点中被绿色标记的点,是边被割去的点。由此可以根据题意来输出一组最小割方案。

事实上,你会发现从源点开始 DFS 的过程,与 König 定理中标记点的过程非常相似。沿着未满流的原图边走,就是沿着二分图中的非匹配边走;沿着残余网络中的反向边走,就是沿着二分图中的匹配边走。图三中,红色点是最小点覆盖点集,蓝色点为最大独立集,可以发现最小点覆盖和最小割是完全一致的。也就是说,想要求最小点覆盖,实际上就是求一种最小割的方案。因此网络流图建好以后,不需要上面代码中的 mark 函数,而是直接 DFS 求出 S 点集即可。

回过来看2021 ECfinal 的 H,是让你求最多能有多少组WB交叉的2x2方块,可以根据奇偶性翻转颜色,将题意变为多少组纯白或纯黑的方块。

经过这个转化后,我们就可以套用上面提到的最大独立集的三个步骤:

纯白和纯黑的方块是两个阵营,阵营内互不影响,可以划分成一个二分图;如果两个方块有相交部分,那就不能同时满足一黑一白,因此将其左右连边;最后求出最大独立集就是最多可以留多少纯色方块。

换个方式,用最小割来理解,就是把所有冲突的路径,通过割掉左边点或者割掉右边点,使其无法形成增广路。

可以看出,最大独立集和最小割的思想是同源的。


另外从OIwiki搬来一点关于最小割方案的补充:

如果需要在最小割的前提下最小化割边数量,那么先求出最小割,把没有满流的边容量改成无穷大,满流的边容量改成1,重新跑一遍最小割就可求出最小割边数量;如果没有最小割的前提,直接把所有边的容量设成1,求一遍最小割就好了。

下面左图为原图上最小割的方案,右图为所有满流边容量改为1后的最小割方案:

切糕模型

BZOJ 3144 [HNOI2013] 切糕

一个比较经典的省选题,这题最小割的建图方式还是比较妙的,不过我们也可以从中提炼出一个模型来。

为什么要把切糕这题放在这里讲,因为提炼出的模型和上面的最小割方案有很大的关联。


先回顾下这题的建图方式:如果相邻两条路所切的点距离超过d,那么我们认为不满足题意,因此从一条路的下游点,向相邻路距离为d的上游点连一条边权为 inf 的边,这样如果这两条路选点距离超过d,还会存在一条额外的增广路来进行修正。(没图不好理解,具体看原题题解)

这个做法比较难想到,会让人觉得难以理解,我们换个角度进行题意转化:

相邻两条路选的两个点距离不超过d,如果我们把所有上游点向距离为d的下游点连一条新边(如下图所示),那么原题的要求就变成了:任意一条从源点到汇点的路径上,只能割一条边,求最小割。(由于源点和汇点相邻的边不会被割掉,所以每条路最上游和最下游的点不需要连新边)

为了方便描述,我就把这个任意一条路径只割一条边的模型叫做切糕模型了。

而这个模型的解决思路也很简单:所有的边,复制一条流量为 inf 的反向边,再跑最小割就行了,求方案也是从源点DFS即可。(注意这个前提是所有的点都在源点到汇点的路径上,如果不是,去除那些无用点,再复制反向边)


关于证明,需要好几张图,我懒得画了。同校同学可以看下23年暑假前集训图论专题 Z 题的ppt题解。

简单来讲,可以考虑什么时候会出现跑完最大流后一条路上被割两条边,那一定不可能是只有一条路。在被割掉的两条边中间,一定会有一条从源点过来的路,以及一条通往汇点的路,如果中间建立了流量无穷大的反向边,就可以使源点过来的路和通往汇点的路再产生新的增广路,换一条割掉的边,使原来路径上的两条边不会同时被割掉。

其他的细节可以自行思考下。

平面图最小割

参考经典的bzoj第一题狼抓兔子。如果题目给的是一张平面图,要求出最小割,那么会有一个比较有趣的性质,就是 S 和 T 两个集合可以被一条线划分到平面的两边。

S到T的每一条边,合起来在对偶图中可以形成一条完整的路径,我们只需求出对偶图中的最短路径,就可以求出原图中最小割的方案。


另外还有一道和网络流不相干的题目:CF325D,题目大意是实时判断一个圆柱面是否被割开成上下两部分。

虽然不是网络流题目,但是也用到了 平面图最小割 转 对偶图最短路 的思想。

虽然这题是圆柱,但是可以用化环为链的思想,把圆柱展开成平面并复制一份,将上下两部分割裂开,其实就是求一条完整的路径,从左边某一个点出发,到达右边复制平面的同一个点。

ICPC2023济南E

ICPC2023济南E

这道题目我们需要统计新增一条边后产生增广路的情况数。

也是在残余网络上进行方案统计,不过和最小割方案不同,新增加的边不能只满足 “起点在 S 集合,终点在 T 集合”,还要满足这条边的终点能够从残余网络中到达汇点。

所以这题需要两遍DFS,一遍从源点出发走正向边,一遍从汇点出发走反向边,求出两个点集。新增加的边起点和终点在这两个点集内才算合法。

最大权闭合子图

最大权闭合子图是这样一类问题:

给出一个类似于2-sat的逻辑图,一条边 u 到 v 的含义为选了 u 这个结点,就一定要选 v 这个点。每个点有一个正权值或负权值,如何选点使得总权值和最大。(在这种逻辑图当中,选出的子图一定是闭合子图)

一般图的最大权闭合子图

这类问题并不一定是二分图,一般图的最大权闭合子图是同样的做法。

首先把点分为两个点集,正权的点放在左侧,由源点连一条流量为权值的边;负权的点放在右侧,连向汇点一条流量为负权绝对值的边;其他边正常连接,流量为无穷大。

答案为所有正权的和 - 最大流。证明略


如何输出方案呢?

其实和求最小割方案很相似,甚至更简单。

直接说结论:从源点出发沿着流量不为0的边DFS,走到的点集 S 就是答案的子图。

如果说和求最大独立集的区别,那就是最大权闭合子图不一定是二分图。

2024四川省赛C

gym105222C

这题要求我们使立方体满足,左下角都是黑色,右上角都是白色。

一开始我想的是切一个面,还以为是切糕模型之类的,但是贡献不是来自切断邻边,而是翻转颜色。

队友马上想到了关键的转化:如果一个点是白色,那么这个点上,右,前个方向的点都应该是白色。

我们先将所有点变成黑色点,需要一个初始的代价cost。然后如果一个点被选择,代表将这个点染白,这个点指向的所有点,也需要染白。如果一个点最初是黑色,那么将它染白需要花钱,如果一个点最初是白色,那么由黑变白其实是反悔操作,可以赚钱。赚钱的点就是最大权闭合子图中的正权点,花钱的就是负权点。一共能赚到正权和-最大流,所以最后的总花费就是cost-(正权和-最大流)。

我寻思了一下,发现cost就是正权和啊,所以最后答案直接就是最大流了。

这题还有个要求,左下角必须黑,右上角必须白,那就把这两个点单独算花费,不要连入网络流建图中。

方阵上的一些网络流模型

有很多网络流的题目是建立在方阵上的。

比如网络流24题里就有棋盘类的题目,国际象棋中,相永远走不到另一种颜色的位置上,而马每次必定会走到另一种颜色的位置上。这种天然的奇偶颜色关系,就可以建立起二分图模型。

方阵中经常会出现只有上下左右连线,没有斜边连线的情况,因此不存在奇数环,很容易让人联想到二分图的模型。

有时并不是方阵中原本的点进行建图,而是原方阵中的边,或者整体的某个块儿,视作一个点,也很容易变成网络流的模型。

这里举例说明方阵转网络流的一些模型。

2021 ECfinal H

2021 ECfinal H,还是上面那道题。

首先这个WB相间就非常迷惑人,如果想不到按照奇偶性进行颜色翻转,就很容易想偏。

在方阵平面上,相邻位置的互斥关系可以转化为网络流二分图的中间边,比如这题中,相邻的2x2方块不可能是一黑一白,存在着互斥关系。

不过这题不是单纯的将所有块儿分到二分图的两侧,因为有些方块是四个问号,既可以是白色块,也可以是黑色块。因此每个位置需要拆成两个点,左侧点表示将这个位置涂成全白,右侧点表示将这个位置涂成全黑,因此同一个位置的左右两个点也是互斥的,需要连一条边。再将其他八个方向有重叠部分的互斥关系连边。跑一个最大独立集。

CF1404E

CF1404E

用长条铺满方阵中要求的位置,题意就非常的网络流。

因为长条是不允许拐弯的,因此我们不允许有L型的几个位置合在一起的情况。我们把两个位置合一起的操作,看做是选择两个位置中间的点,那么不允许L型的合并,也就是不允许一个位置同时选择相邻的两个点。

将这些有冲突的点进行连边,我们会发现由于平面的性质,它也是一张二分图,跑一个最大独立集,就是最多能进行几次合并。

每一次合并可以减低一点费用,将 '#' 的数量减去合并的最大数量为最终答案。


另外再讲一个和这题题意很像的,但正解不是网络流:江苏省赛J

题意是用一些1*k的骨牌覆盖方阵,骨牌不能重叠或者有相邻边,求最大能覆盖的权值。

骨牌没有相邻边意味着选择的所有点不能出现L型的三个点,而不能出现L型的三个点,就是任意2x2的小方块内最多选两个点。

本来以为可以建成二分图,左边点表示2x2的小方块,右边点表示每一个位置,左边点连汇点流量是2来控制方块内点数。结果发现不行,这条流量为2的边,并不能限制方块内的点数,因为这些位置也可以从其他相邻的方块找流量流进来。

目前还没想到网络流做法,估计是没法做。数据范围很小,正解是状压,不在这里讲了。

DAG转二分图

售货员问题?

先来讲一个很像售货员问题的题目:

n 个点 m 条边的 DAG,你可以花费 \(a_i\) 传送到 \(i\) ,求每个点恰好经过一次走完所有点的最小花费。


有个上下界的模型可以解决这个问题,不过没有必要,可以用按照出度入度拆点的方式将DAG转成二分图来解决。

具体的,每个点拆成左右侧两个点;由于每个点恰好经过一次,视作入度为1,每个右侧点向汇点连一条流量为1的边;每个点可以走到其他点一次,视为出度为1,从源点向左侧点连一条流量为1的边;原图中的边,从左侧点连接到右侧点,流量为1,费用为原图边权。

这时跑费用流。中间的某条边满流,说明路径中选择了这个点;连向汇点的边满流,说明这个点被到达。

现在的图最大流不是n,这是因为在没有传送时,一些点是可能无法到达的。比如这题没说一开始在DAG中的起点,而是通过传送来到DAG中,我们考虑将传送的路线加入二分图中。

通过原图中的边从 u 走到点 v ,也就是二分图左侧点 u 连向右侧点 v 的这条路;直接传送到点 v ,就是不需要花费左侧点的出度(每个点的出度只能用一次),而是直接从源点连一条到右侧点 v ,费用为 \(a_v\) 的边。

将这两种移动方式的边都连上,图就算建完了,跑费用流就是每个点经过一次的答案。

可以发现,这题中从源点连向右侧点这一个补流的操作,和上面讲到的二分图最大权匹配时的补流思想是很相似的。

最小生成树?

再讲一个很像最小生成树的问题:CF277E

平面上有一些点,每个点只能向高度小于它的点连边,且最多连出两条边,边权为两点欧几里得距离,求连接所有点的最小边权。也就是,求出一棵最小生成二叉树。


与上一个例题思路一致,我们将每个点拆成二分图左右两点,左边点代表出度,右边点代表入度。

每个点最多连出两条边,因此从源点向左边点连一条流量为2的边;每个点只有一个入度,因此右侧点向汇点连一条流量为1的边;而中间所有可以连接的边,都连一条流量为1,费用为欧几里得距离的边。

跑费用流,答案就是最小生成二叉树。

这题没有指定起点,但是默认从最高的点出发,最高的点入度为0,它不需要向汇点连边。如果最高的点不止一个,那么输出无解。如果右侧点连向汇点的边不能满流,说明也是无解,含义就是它们无法获得足够多的入边。

为什么两题都需要保证是DAG?

我们都知道售货员问题是npc的,因为这种建图的前提是DAG。

我们再来思考下两道题的路线方案:

第一题中,我们可以使用传送,传送完之后可以从落点走一条链,所有的链不重不漏覆盖所有的点。

第二题中,二叉树的第二条出边也相当于传送到了该点,并从该点开始走一条链,只不过这条链的起点挂在了以前经过的点上。

这样一来,我们的链在DAG中都是有始有终的,一个出边对应另一个点的入边。

如果DAG改成了一般图,就打破了这个平衡,我们甚至可以不使用传送,而是在二分图中跑出一个 1->2, 2->3, 3->1 的环作为费用,这样同样是满足了每个点访问一次,但是却无法找到一条进入环的路线,无论是从其他点还是传送。

第二题也不能是DAG,因为我们的建图只能保证:每个点出边上限为2,入边必须为1,但无法保证图的联通性问题。因为这两个限制在一般图中可能会以基环树森林的形式出现,即某个点出边连向了自己的祖先,从而认为祖先结点不需要从更高的祖先连边,造成图不连通。而在DAG中,只要规定了入边为1,那么一定是生成的子图一定是一棵树。

写在后面

感觉,也没什么需要写在后面的了。

就是不定期会更新吧,如果以后看到类似的模型也会丢到这篇随笔里来。

上下界可能也会做些总结,不过就不往这里丢了,这篇已经够长了。

真能看完的读者希望能有点收获吧,哪怕只是几道例题的指路也好。

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

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

相关文章

解析ORB-SLAM3的源码

随着计算机视觉与机器人技术的发展,SLAM(同步定位与地图构建)技术在自动导航、机器人和无人机领域中起着至关重要的作用。作为当前最先进的SLAM系统之一,ORB-SLAM3因其卓越的性能和开源特性,备受关注。本文将详细解析ORB-SLAM3的源码,帮助读者更好地理解其内部机制。 一、…

Javascript-this/作用域/闭包

this & 作用域 & 闭包this的核心,在大多数情况下,可以简单地理解为谁调用了函数,this就指向谁。但请注意,这里不包括通过call、apply、bind、new操作符或箭头函数进行调用的特殊情况。在这些特殊情况下,this的指向会有所不同。 this的值是在函数运行时根据调用方式…

TIM1比较模式

暂不讨论捕获功能,简化下面的描述方便阅读理解。 -------------------------------------------------------------------------------- 13.4.14 TIM1 比较寄存器 1(TIMx_CCR1)    CCR1[15:0]: 比较通道1的值 (Compare 1 value) 若CC1 通道配置为输出:CCR1包含了装入比较…

[C++ Primer] 顺序容器

记录C++中STL标准模板库的常见操作顺序容器 顺序容器概述下标列出了标准库中的顺序容器,所有顺序容器都提供了快速顺序访问元素的能力。这些容器在以下方面都有不同的性能折中:向容器添加或从容器中删除元素的代价 非顺序访问容器中元素的代价2. 若不确定应该使用哪种容器,可…

Centos7.6下安装配置Jenkins

目前,网上很多关于Jenkins持续集成工具在Centos上部署教程,但发现部署完之后,基本都是不能使用,大部分是关于版本问题的报错, 都会提示让我们更新jenkins到比较新的版本,而更新到新版Jenkins又必须使用JDK11以上的版本,而我开发、测试用的环境JDK8版本, 一旦升级JDK,很…

VSCode 中 Markdown Preview Enhanced 插件利用 Chrome (Puppeteer) 导出 PDF 文件使用说明与问题解决

准备 预先安装好 Chrome 浏览器。 使用方法 右键选择 Chrome (Puppeteer)。设置 Puppeteer 通过 front-matter 即在 markdown 文档开头加上 yaml 格式的配置代码 --- puppeteer:format: "A4"scale: 1.0margin:top: 2cmright: 3cmbottom: 2cmleft: 3cm ---这里 format…

全网最适合入门的面向对象编程教程:03 类和对象的Python实现-为自定义类添加属性

本文主要介绍了,当使用Python创建自定义类时,如何为其添加属性,包括为类和实例添加属性两种,以及如何获取自定义的属性等内容。摘要: 本文主要介绍了,当使用 Python 创建自定义类时,如何为其添加属性,包括为类和实例添加属性两种,以及如何获取自定义的属性等内容。 往…

全网最适合入门的面向对象编程教程:03 类和对象的Python实现-使用Python创建类

本文主要介绍了,当使用Python创建自定义类时,如何为其添加属性,包括为类和实例添加属性两种,以及如何获取自定义的属性等内容。摘要: 本文主要介绍了,当使用 Python 创建自定义类时,如何为其添加属性,包括为类和实例添加属性两种,以及如何获取自定义的属性等内容。 往…

Centos7下安装配置MySQL5.7

本次安装的版本是在Centos7.6版本下安装配置mysql5.7版本。具体操作步骤如下: 1. 首先通过wget命令,下载MySQL源安装包: wget https://dev.mysql.com/get/mysql57-community-release-el7-11.noarch.rpm 安装MySQL源: yum localinstall mysql57-community-release-el7-11.noar…

Hugging Face Accelerate 两个后端的故事:FSDP 与 DeepSpeed

社区中有两个流行的 零冗余优化器(Zero Redundancy Optimizer,ZeRO) 算法实现,一个来自 DeepSpeed,另一个来自 PyTorch。Hugging Face Accelerate 对这两者都进行了集成并通过接口暴露出来,以供最终用户在训练/微调模型时自主选择其中之一。本文重点介绍了 Accelerate 对…

自制键盘(一)

概述 这个项目的灵感来源是稚晖君的客制化键盘项目,看到瀚文就觉得很震撼,就想自己也做一把试试。正好最近也正好在学嵌入式,顺便巩固一下最近所学的知识、也可以多了解一点技术栈。不过由于技术首先所以先做一把小键盘试试手。 项目整体思路 整个项目大致可以分为三个部分,…

尝试使用 Python 截屏并录屏

( 本文的完整版地址在 https://www.ccgxk.com/?post=494 ) 我在去年,曾经尝试过一个大胆的东西,就是使用 Python 写了个程序来录屏,以此给自己一种“期待感”,当时有没有效果我忘了,但是现在我又将这个项目捡了起来。界面是长上面那个样子,集成了项目名设置、开始录…

Compose 延迟列表踩过的坑

问题 在使用 Jetpack Compose 延迟列表时遇到一个坑,简单记录一下。直接上代码:这个代码看起来也没有什么问题,滑动正常,点击滑动到顶部也正常。 但是极端操作:在一边滑动列表一边点击按钮,就出问题了。这样再点击按钮,就不生效了。从日志来看,点击时协程发射值没有问题…

代码随想录算法训练营第22天 | 77.组合 216.组合总和 17.电话号码的字母组合

77.组合 给定两个整数 n 和 k,返回 1 ... n 中所有可能的 k 个数的组合。 解题 只能取比它大的,所以有个参数startindex 参数:一维数组单个组合path,二维数组结果集result,总数n,组合大小k,搜索结果的开始索引startindex 终止条件:path.size=k点击查看代码 class Solut…

(四)详解RLHF

一直都特别好奇大模型的强化学习微调是怎么做的,网上虽然相关文章不少,但找到的文章都是浅尝辄止说到用PPO训练,再细致深入的就没有讲了。。。只能自己看一看代码,以前搞过一点用PPO做游戏,感觉和语言模型PPO的用法不太一样。在游戏场景,每个step给环境一个action之后,a…

模拟集成电路设计系列博客——8.1.1 锁相环基本介绍

8.1.1 锁相环基本介绍 几乎所有的数字,射频电路以及大部分的模拟电路。不幸的是,集成电路振荡器本身并不适合用于高性能电路中的频率/时间参考源。一个主要的问题是它们的震荡频率并不能精确知道。更进一步的,集成电路振荡器的时钟抖动(可以被认为是频率上的随机波动)对于…

(三)使用 PPO 算法进行 RLHF 的 N 步实现细节

使用 PPO 算法进行 RLHF 的 N 步实现细节 当下,RLHF/ChatGPT 已经变成了一个非常流行的话题。我们正在致力于更多有关 RLHF 的研究,这篇博客尝试复现 OpenAI 在 2019 年开源的原始 RLHF 代码库,其仓库位置位于 openai/lm-human-preferences。尽管它具有 “tensorflow-1.x” …

JMeter安装目录简单说明

一 前言 环境: window 10 JMeter5.3 JMeter安装目录的文件通常容易被忽略,注意力全放在JMeter本身的各个功能的使用上。 但在前面的学习中我们发现了熟悉安装目录的必要性。 如jmeter.properties这个文件,之前的文章中就经常查看或者修改,还有一些日志文件也在安装目录中 二…

G61【模板】线性基 P3812 线性基

视频链接: G23 线性方程组 高斯消元法 - 董晓 - 博客园 (cnblogs.com) P3812 【模板】线性基 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)// 线性基 O(63*n) #include <iostream> #include <cstring> #include <algorithm> using namespace std;typede…