Algorithem Review 5.2 图论

网络流

  • 设源点为 s s s,汇点为 t t t,每条边 e e e 的流量上限为 c ( e ) c(e) c(e),流量为 f ( e ) f(e) f(e)
  • 指对于某一顶点集合 P ⊂ V P \subset V PV,从 P P P 出发指向 P P P 外部的那些原图中的边的集合,记作割 ( P , V / P ) (P, V /\ P) (P,V/ P)。这些边的容量被称为割的容量。若 s ∈ P , t ∈ V / P s\in P, t\in V /\ P sP,tV/ P,则称此时的割为 s − t s-t st 割。
  • 对于任意的 s − t s-t st F F F 和任意的 s − t s-t st ( P , V / P ) (P,V/\ P) (P,V/ P) 割,由每个点的流量平衡条件得:
    F 的流量 = P 出边总流量 − P 入边总流量 ≤ 割的容量 F 的流量 = P出边总流量 - P 入边总流量 \le 割的容量 F的流量=P出边总流量P入边总流量割的容量
  • 对于在残量网络中不断增广得到的流 F F F,设其对应的残量网络中从 s s s 出发可到达的顶点集为 S S S,则对于 S S S 指向 V / S V/\ S V/ S 的边 e e e f ( e ) = c ( e ) f(e) = c(e) f(e)=c(e),而对 V / S V/\ S V/ S 指向 S S S 的边有 f ( e ) = 0 f(e) = 0 f(e)=0,则:
    F 的流量 = S 出边总流量 − S 入边总流量 = S 出边总流量 = 割的容量 F 的流量 = S 出边总流量 - S入边总流量 = S出边总流量 = 割的容量 F的流量=S出边总流量S入边总流量=S出边总流量=割的容量
  • 因而 F F F 为最大流,同时 ( S , V / S ) (S,V/\ S) (S,V/ S) 为最小割,即最大流等于最小割

Dinic 算法

  • 主要思想即每次寻找最短的增广路,构造分层图,并沿着它多路增广。
  • 每次多路增广完成后最短增广路长度至少增加 1,构造分层图次数为 O ( n ) \mathcal O(n) O(n),在同一分层图中,每条增广路都会被至少一条边限制流量(我们称之为瓶颈),显然任意两条增广路的瓶颈均不相同,因而增广路总数为 O ( m ) \mathcal O(m) O(m),加上当前弧优化,我们就能避免对无用边多次检查,寻找单条增广路的时间复杂度为 O ( n ) \mathcal O(n) O(n),总时间复杂度 O ( n 2 m ) \mathcal O(n^2m) O(n2m)
  • 这只是一个粗略的上界,实际的复杂度分析要结合具体的图模型,例如若最大流上限较小(设为 F F F),时间复杂度 O ( F ( n + m ) ) \mathcal O(F(n+m)) O(F(n+m))
const int N = 1e4 + 5;
const int M = 2e5 + 5;
int nxt[M], to[M], cap[M], adj[N], que[N], cur[N], lev[N];
int n, m, src, des, qr, T = 1;inline void linkArc(int x, int y, int w)
{nxt[++T] = adj[x]; adj[x] = T; to[T] = y; cap[T] = w;nxt[++T] = adj[y]; adj[y] = T; to[T] = x; cap[T] = 0;	
}inline bool Bfs()
{for (int x = 1; x <= n; ++x)	cur[x] = adj[x], lev[x] = -1;// 初始化具体的范围视建图而定,这里点的范围为 [1,n]que[qr = 1] = src;lev[src] = 0;for (int i = 1; i <= qr; ++i){int x = que[i], y;for (int e = adj[x]; e; e = nxt[e])if (cap[e] > 0 && lev[y = to[e]] == -1){lev[y] = lev[x] + 1;que[++qr] = y;if (y == des)return true;}}return false;
} inline ll Dinic(int x, ll flow)
{if (x == des)return flow;int y, delta; ll res = 0;	for (int &e = cur[x]; e; e = nxt[e]) if (cap[e] > 0 && lev[y = to[e]] > lev[x]){delta = Dinic(y, Min(flow - res, (ll)cap[e]));if (delta){cap[e] -= delta;cap[e ^ 1] += delta;res += delta;if (res == flow)break ; //此时 break 保证下次 cur[x] 仍有机会增广 }} if (res != flow)lev[x] = -1;return res; 
}inline ll maxFlow()
{ll res = 0;while (Bfs())res += Dinic(src, Maxn);return res;
}
  • 单位网络 在该网络中,所有边的流量均为 1,除源汇点以外的所有点,都满足入边或者出边最多只有一条。
  • 结论 对于包含二分图最大匹配在内的单位网络, Dinic \text{Dinic} Dinic 算法求解最大流的时间复杂度为 O ( m n ) \mathcal O(m\sqrt n) O(mn )

证明 对于单位网络,每条边最多被考虑一次,一轮增广的时间复杂度为 O ( m ) \mathcal O(m) O(m)

假设我们已经完成了前 n \sqrt n n 轮增广,还需找到 d d d 条增广路才能找到最大流,每条增广路的长度至少为 n \sqrt n n 。这些增广路不会在源点和汇点以外的点相交,因而至少经过了 d n d\sqrt n dn 个点, d ≤ n d \le \sqrt n dn ,则至多还需增广 n \sqrt n n 轮,总时间复杂度 O ( m n ) \mathcal O(m\sqrt n) O(mn )

经典模型

  • 二者选其一的最小割 n n n 个物品和两个集合 A , B A,B A,B,若第 i i i 个物品没有放入 A A A 集合花费 a i a_i ai,没有放入 B B B 集合花费 b i b_i bi,还有若干个限制条件,若 u i u_i ui v i v_i vi 不在一个集合则花费 w i w_i wi
    • 源点 s s s 向第 i i i 个点连一条容量为 a i a_i ai 的边,第 i i i 个点向汇点 t t t 连一条容量为 b i b_i bi 的边,在 u i u_i ui v i v_i vi 之间连容量为 w i w_i wi 的双向边,最小割即最小花费。
  • 最大权闭合子图 给定一张有向图,每个点都有一个权值(可为负),选择一个权值和最大的子图,使得子图中每个点的后继都在子图中。
    • 若点权为正,则 s s s 向该点连一条容量为点权的边。
    • 若点权为负,则该点向 t t t 连一条容量为点权的相反数的边。
    • 原图上所有边的容量设为 + ∞ +\infty +
    • 则答案为正点权之和减去最小割。
  • 分糖果问题 n n n 个糖果 m m m 个小孩,小孩 i i i 对糖果 j j j 有偏爱度 a i , j = 1 / 2 a_{i,j} = 1/2 ai,j=1/2,设 c i , j = 0 / 1 c_{i,j} = 0/1 ci,j=0/1 表示小孩 i i i 是否分得了糖果 j j j,小孩 i i i 觉得高兴当且仅当 ∑ j = 1 n c i , j a i , j ≥ b i \sum\limits_{j = 1}^{n} c_{i,j} a_{i,j}\ge b_i j=1nci,jai,jbi,判断是否存在方案使所有小孩都高兴。
    • 偏爱度 a i , j = 1 / 2 a_{i,j} = 1/2 ai,j=1/2 不好建图,转换思路先分配所有 a i , j = 2 a_{i,j} = 2 ai,j=2 的糖果。
    • s s s 向所有糖果连一条容量为 1 的边,小孩 i i i t t t 连一条容量为 ⌊ b i 2 ⌋ \lfloor \frac{b_i}{2} \rfloor 2bi 的边。
    • 对于所有满足 a i , j = 2 a_{i,j} = 2 ai,j=2 的边,令糖果 j j j 向小孩 i i i 连一条容量为 1 的边。
    • 求得最大流 a n s ans ans,则存在方案当且仅当 a n s + n ≥ ∑ j = 1 m b i ans + n\ge \sum \limits_{j = 1}^{m}b_i ans+nj=1mbi
  • 动态流问题 宽为 w w w 的河上有 n n n 块石头,第 i i i 块坐标 ( x i , y i ) (x_i,y_i) (xi,yi),同一时刻最大承受人数为 c i c_i ci,现有 m m m 个游客想要渡河,每人每次最远跳 d d d 米 ,单次耗时 1 秒,求全部渡河的最少时间( n , m ≤ 50 n,m \le 50 n,m50)。
    • 答案取值范围较小可暴力枚举,将每一时刻的石头都视作一点,在石头上跳跃可视作从第 t t t 时刻的石头 i i i 跳向第 t + 1 t + 1 t+1 时刻的石头 j j j,每次将时刻加一,建出新的点和边后跑最大流,直至总流量大于等于 m m m

费用流

  • 在最大流的前提下使该网络总花费最小。

SSP 算法

  • 每次寻找单位费用最小的增广路进行增广,直至图中不存在增广路为止。

  • 设流量为 i i i 的时候最小费用为 f i f_i fi,假设初始网络上没有负圈, f 0 = 0 f_0 = 0 f0=0

  • 假设用 SSP \text{SSP} SSP 算法求出的 f i f_i fi 是最小费用,我们在 f i f_i fi 的基础上,找到一条最短的增广路,从而求出 f i + 1 f_{i + 1} fi+1,此时 f i + 1 − f i f_{i + 1} - f_i fi+1fi 就是这条最短增广路的长度。

  • 假设存在更小的 f i + 1 f_{i + 1} fi+1,设其为 f i + 1 ′ f_{i+1}' fi+1,则 f i + 1 ′ − f i f'_{i + 1} - f_i fi+1fi 一定对应一个经过至少一个负圈的增广路。若残量网络中存在至少一个负圈,则可在不增加 s s s 流出的流量的情况下使费用减小,与 f i f_i fi 是最小费用矛盾。

  • 综上, SSP \text{SSP} SSP 算法可以正确求出无负圈网络的最小费用最大流,设最大流为 F F F,总时间复杂度 O ( F n m ) \mathcal O(Fnm) O(Fnm)

const int N = 5e3 + 5;
const int M = 1e5 + 5;
int nxt[M], to[M], cap[M], que[M], cst[M], adj[N], dis[N];
bool vis[N]; int n, m, src, des, ans, T = 1, qr;inline void linkArc(int x, int y, int w, int z)
{nxt[++T] = adj[x]; adj[x] = T; to[T] = y; cap[T] = w; cst[T] = z;nxt[++T] = adj[y]; adj[y] = T; to[T] = x; cap[T] = 0; cst[T] = -z;	
}inline bool SPFA()
{for (int x = 1; x <= n; ++x)dis[x] = Maxn, vis[x] = false;// 初始化具体的范围视建图而定,这里点的范围为 [1,n]dis[que[qr = 1] = src] = 0;for (int i = 1, x, y; i <= qr; ++i){vis[x = que[i]] = false;for (int e = adj[x]; e; e = nxt[e])if (cap[e] > 0 && dis[y = to[e]] > dis[x] + cst[e]){dis[y] = dis[x] + cst[e];if (!vis[y])vis[que[++qr] = y] = true;}}return dis[des] < Maxn;
}inline int Dinic(int x, int flow)
{if (x == des){ans += flow * dis[des];return flow;}vis[x] = true;int y, delta, res = 0;for (int e = adj[x]; e; e = nxt[e])if (!vis[y = to[e]] && cap[e] > 0 && dis[y] == dis[x] + cst[e])// vis 数组防止 dfs 在总费用为 0 的环上死循环 {delta = Dinic(y, Min(flow - res, cap[e]));if (delta){cap[e] -= delta;cap[e ^ 1] += delta;res += delta;if (res == flow)break ;	} }return res;
}inline int MCMF()
{ans = 0;int res = 0;while (SPFA())res += Dinic(src, Maxn);return res;
}

经典模型

  • 餐巾计划问题 一家餐厅在接下来的 T T T 天内需用餐巾,第 i i i 天需要 r i r_i ri 块干净餐巾,餐厅可任意购买单价为 p p p 的干净餐巾,或者将脏餐巾送往快洗部(单块餐巾需洗 m m m 天,花费 f f f)或慢洗部(单块餐巾需洗 n n n 天,花费 s s s),求这 T T T 天内的最小花费。
    • 主要的难点在于需将干净餐巾和脏餐巾区分开,第 i i i 天分设点 i , i ′ i,i' i,i,流向这两点的流量分别表示第 i i i 天的干净餐巾和脏餐巾。
    • s s s i i i 连一条容量为 + ∞ +\infty + 、费用为 p p p 的边, i i i t t t 连一条容量为 r i r_i ri、费用为 0 的边。
    • s s s i ′ i' i 连一条容量为 r i r_i ri、费用为 0 的边, i ′ i' i i + m i + m i+m 连一条容量为 + ∞ +\infty +,费用为 f f f 的边,向 i + n i + n i+n 连一条容量为 + ∞ +\infty +,费用为 s s s 的边,向 ( i + 1 ) ′ (i + 1)' (i+1) 连一条容量为 + ∞ +\infty +,费用为 0 0 0 的边。
    • 显然该建图能使到 t t t 的边满流,则最小费用即为所求。
  • 费用流转二分图最大匹配 若除去费用的建图为二分图且费用不为 0 的边均在二分图一侧,可将有费用的边从小到大排序,按照这一顺序跑匈牙利算法,容易证明最大匹配即对应最小费用,可将时间复杂度降至 O ( n m ) \mathcal O(nm) O(nm)

二分图最大匹配

  • 记图 G = ( V , E ) G = (V,E) G=(V,E)
    • 匹配 G G G 中两两没有公共端点的边集合 M ⊆ E M \subseteq E ME
    • 边覆盖 G G G 中的任意顶点都至少是 F F F 中某条边的边集合 F ⊆ E F \subseteq E FE
    • 独立集 G G G 中两两互不相连的顶点集 S ⊆ V S \subseteq V SV
    • 点覆盖 G G G 中任意边都有至少一个端点属于 P P P 的顶点集合 P ⊆ V P \subseteq V PV
  • 结论1 对于不存在孤立点的图, ∣ 最大匹配 ∣ + ∣ 最小边覆盖 ∣ = ∣ V ∣ |最大匹配|+|最小边覆盖| = |V| 最大匹配+最小边覆盖=V

证明 设最大匹配数为 x x x,则其覆盖的点数为 2 x 2x 2x,剩余点两两之间没有边。则最少需要增加 ∣ V ∣ − 2 x |V| - 2x V2x 条边才能将所有点覆盖,则最小边覆盖数为 x + ∣ V ∣ − 2 x = ∣ V ∣ − x x + |V| - 2x = |V| - x x+V2x=Vx

  • 结论2 ∣ 最大独立集 ∣ + ∣ 最小点覆盖 ∣ = ∣ V ∣ |最大独立集| + |最小点覆盖| = |V| 最大独立集+最小点覆盖=V

证明 只需证明独立集和点覆盖一一对应且互为关于 V V V 的补集即可。取一个点覆盖关于 V V V 的补集,若其不是一个独立集,则存在两点有公共边,不难发现这与点覆盖的定义矛盾。

  • 结论3二分图中, ∣ 最大匹配 ∣ = ∣ 最小点覆盖 ∣ |最大匹配|=|最小点覆盖| 最大匹配=最小点覆盖

证明 设最大匹配数为 x x x,即让匹配中的每条边都和其一个端点关联。 x x x 个点是足够的,否则若存在一条边未被覆盖,加入这条边能得到一个更大的匹配。 x x x 个点是必需的,因为匹配的 x x x 条边两两无公共点。

  • 结论4有向无环图中, ∣ 最小点不相交路径覆盖 ∣ + ∣ 最大匹配 ∣ = ∣ V ∣ |最小点不相交路径覆盖|+|最大匹配|=|V| 最小点不相交路径覆盖+最大匹配=V。这里的最大匹配指的是,将原图每个点拆成入点和出点两点,对于有向边 x → y x \to y xy,将 x x x 的入点向 y y y 的出点连边,在该二分图上求得的最大匹配。

    • 若需求 ∣ 最小点可相交路径覆盖 ∣ |最小点可相交路径覆盖| 最小点可相交路径覆盖,可以每个点为起点 BFS 求出传递闭包,传递闭包上建图即可,传递闭包中图的边数可能达到 O ( ∣ V ∣ 2 ) \mathcal O(|V|^2) O(V2),时间复杂度 O ( ∣ V ∣ ∣ E ∣ + ∣ V ∣ 2.5 ) \mathcal O(|V||E|+|V|^{2.5}) O(V∣∣E+V2.5),空间复杂度 O ( ∣ V ∣ 2 ) \mathcal O(|V|^2) O(V2),输出方案记录每个入点的匹配点即可,时间复杂度 ( ∣ V ∣ ) \mathcal (|V|) (V)
    • ∣ E ∣ |E| E 较小,也可以不求传递闭包,将有向边的容量设为 + ∞ +\infty +,并将所有的出点向对应的入点连一条容量为 + ∞ +\infty + 的边,即可实现传递闭包的效果,直接跑网络流即可,因为最大流上限为 ∣ V ∣ |V| V,时间复杂度 O ( ∣ V ∣ ( ∣ V ∣ + ∣ E ∣ ) ) \mathcal O(|V|(|V|+|E|)) O(V(V+E)),空间复杂度 O ( ∣ V ∣ + ∣ E ∣ ) \mathcal O(|V|+|E|) O(V+E),实际上严格优于前述做法。该做法的输出方案较为麻烦,具体来说,我们根据所有匹配边建出一张图,若一个点的出边比入边多则它可以作为一条链的起点,暴力往下跳即可,实现时将本质相同的边压缩成一条可将空间复杂度降至 O ( ∣ V ∣ + ∣ E ∣ ) \mathcal O(|V|+|E|) O(V+E),时间复杂度 O ( ∣ V ∣ 2 ) \mathcal O(|V|^2) O(V2),参考代码如下:
    	// C 为二分图一侧的点数,src = 2 * C + 1// 注意孤立点以及删去一条链可能会产生新的起点的情况for (int x = 1; x <= C; ++x)for (int e = adj[x]; e; e = nxt[e])if (to[e] > C && to[e] < src && to[e] - C != x && cap[e ^ 1] > 0){re[x].emplace_back(std::make_pair(to[e] - C, cap[e ^ 1])); ++lre[x];sre[x] += cap[e ^ 1];ind[to[e] - C] += cap[e ^ 1]; }tis = 0;for (int t = 1; t <= C; ++t){for (int x = 1; x <= C; ++x)while (sre[x] > ind[x]){++tis;int u = x;ans[u] = tis;while (sre[u]){pir &v = re[u][lre[u] - 1];int vid = v.first;if (--v.second == 0)re[u].pop_back(), --lre[u];--sre[u];u = vid;ans[u] = tis;--ind[u];}}}
    

证明 只需证明二分图中匹配与原图中的路径覆盖一一对应且总和为 ∣ V ∣ |V| V。对于每个没有匹配边的出点,我们都能构造一条路径,若其对应的入点存在匹配边,则将该匹配边加入该路径同时继续考虑该匹配边的出点直至其对应的入点不存在匹配边。得到的所有路径恰能覆盖所有点,且没有匹配边的出点和入点恰好能两两配对分别构成所有路径的起点和终点。

  • Dilworth定理 对于任意有限偏序集,其最大反链中的元素个数必等于最小链划分中链的个数。
    • 有限偏序集的最小链划分即其哈斯图对应的有向无环图的 ∣ 最小点可相交路径覆盖 ∣ |最小点可相交路径覆盖| 最小点可相交路径覆盖,用上述方法求解即可。

证明 m m m 为最大反链的元素个数, ∣ X ∣ = n |X| = n X=n,只要证明偏序集 X X X 可被划分成 m m m 个链即可。

考虑用归纳法证明,当 n = 1 n = 1 n=1 时显然成立,下面证明 n > 1 n > 1 n>1 时的情形,设该有限偏序集中所有极小点构成的集合为 L L L,所有极大点构成的集合为 G G G,分两种情况讨论:

  1. 若存在最大反链 A A A,使得 A ≠ L A \not = L A=L A ≠ G A \not = G A=G。构造:
    A + = { x ∣ x ∈ X ∧ ∃ a ∈ A , a ≤ x } A − = { x ∣ x ∈ X ∧ ∃ a ∈ A , x ≤ a } A^+=\{x|x\in X \wedge \exist a\in A,a\le x\} \\ A^-=\{x|x\in X \wedge \exist a\in A,x \le a\} \\ A+={xxXaA,ax}A={xxXaA,xa}
    则容易得到 ∣ A + ∣ < ∣ X ∣ |A^+|<|X| A+<X ∣ A − ∣ < ∣ X ∣ |A^-|<|X| A<X A + ∪ A − = X , A + ∩ A − = A A^+\cup A^- =X,A^{+}\cap A^-=A A+A=X,A+A=A,由归纳假设可将 A + A^{+} A+ A − A^{-} A m m m 链划分拼接起来即可得到 X X X m m m 链划分。

  2. 若只存在反链 A = L A = L A=L A = G A = G A=G,取极小元 x x x 和极大元 y y y 满足 x ≤ y x\le y xy x , y x,y x,y 可相等),则由归纳假设 X − { x , y } X -\{x,y\} X{x,y} 最大反链的元素个数为 m − 1 m - 1 m1,存在 m − 1 m - 1 m1 链划分,增加链 x ≤ y x\le y xy 可得到 X X X m m m 链划分。

  • Dilworth定理的对偶形式 最长链中元素个数必等于最小反链划分中反链的个数。

证明 设最长链的长度为 m m m,最小反链划分的数目为 M M M

  1. 由于在任意一个反链中选取超过一个元素都违反链的定义,容易得到 m ≤ M m \le M mM
  2. 考虑每次删去当前偏序集中的所有极小点,恰好删除 m m m 次能够将所有点删除,设第 i i i 次删点构成的极小点集合为 A i A_i Ai,则 A 1 , A 2 , … , A m A_1,A_2,\dots,A_m A1,A2,,Am 构成一个反链划分,故有 M ≤ m M \le m Mm

综上所述, m = M m = M m=M,原命题得证。

匈牙利算法

  • 从每个点出发尝试找到一条增广路,时间复杂度 O ( n m ) \mathcal O(nm) O(nm)
inline bool Hungary(int x)
{int y;for (arc *e = adj[x]; e; e = e->nxt)if (!mateR[y = e->to])return mateR[y] = x, true;for (arc *e = adj[x]; e; e = e->nxt){if (vis[y = e->to] == tis)continue ;vis[y] = tis;if (Hungary(mateR[y]))return mateR[y] = x, true;}return false;
}inline int maxMatch()
{int cnt = 0;for (int i = 1; i <= n; ++i){++tis;if (Hungary(i))++cnt;} return cnt;
}

二分图最大权匹配

Kuhn-Munkres算法

  • 该算法用于 O ( n 3 ) \mathcal O(n^3) O(n3) 求二分图的最大权完美匹配,若二分图左右部的点数不相同,需将点数补至相同,并将所有不存在的边的权设为 0。
  • 若题目对是否是完备匹配有要求,需将不存在的边设为 − ∞ -\infty (具体值需保证一旦选这种边就比所有不选这种边的方案更劣),此时也能处理原图边权有负数的情况。
  • 可行顶标 对于二分图 < X , E , Y > <X,E,Y> <X,E,Y>,对于 x ∈ X x \in X xX 分配权值 labx ( x ) \text{labx}(x) labx(x),对于 y ∈ Y y\in Y yY 分配权值 laby ( y ) \text{laby}(y) laby(y),对于所有边 ( x , y ) ∈ E (x,y)\in E (x,y)E 满足 w ( x , y ) ≤ labx ( x ) + laby ( y ) w(x,y) \le \text{labx}(x) + \text{laby}(y) w(x,y)labx(x)+laby(y)
  • 相等子图 在一组可行顶标下原图的生成子图,包含所有点但只满足包含 labx ( x ) + laby ( y ) = w ( x , y ) \text{labx}(x) + \text{laby}(y) = w(x,y) labx(x)+laby(y)=w(x,y) 的边 ( x , y ) (x,y) (x,y)
  • 定理 对于某组可行顶标,若其相等子图内存在完美匹配,该匹配为原图的最大权完美匹配。

证明 设可行顶标下相等子图中的完美匹配为 M ′ M' M,对于原二分图任意一组完美匹配 M M M,其边权和
val ( M ) = ∑ ( x , y ) ∈ M w ( x , y ) ≤ ∑ x ∈ X labx ( x ) + ∑ y ∈ Y laby ( y ) = val ( M ′ ) \text{val}(M) = \sum \limits_{(x,y)\in M}w(x,y) \le \sum\limits_{x\in X}\text{labx}(x) + \sum \limits_{y \in Y} \text{laby}(y) = \text{val}(M') val(M)=(x,y)Mw(x,y)xXlabx(x)+yYlaby(y)=val(M)
故若 M ′ M' M 存在, M ′ M' M 即为最大权完美匹配。

  • 下面的算法过程将证明一定能够通过调整顶标,使得相等子图内存在完美匹配。
  • 初始可行顶标 labx ( x ) = max ⁡ y ∈ Y { w ( x , y ) } , laby ( y ) = 0 \text{labx}(x) = \max\limits_{y\in Y}\{w(x,y)\}, \text{laby}(y) = 0 labx(x)=yYmax{w(x,y)},laby(y)=0,在相等子图内找一个未匹配的点,尝试寻找增广路,若能找到直接增广,否则将形成一棵交错树。
  • 交错树是由从一个未匹配点出发沿着 非匹配边-匹配边 交替的所有路径构成的树,将树中顶点与 X X X 的交集记为 S S S,与 Y Y Y 的交集记为 T T T,令 S ′ = X − S , T ′ = Y − T S' = X - S, T' = Y - T S=XS,T=YT S / S ′ , T / T ′ S/S',T/T' S/S,T/T 程序中分别用 visx ( x ) \text{visx}(x) visx(x) visy ( y ) \text{visy}(y) visy(y) 标示),如下图所示。
    请添加图片描述
  • 在相等子图中:
    • S − T ′ S-T' ST 的边不存在,若其为匹配边违反交错树的定义,若其为非匹配边则会形成增广路或者使交错树扩大。
    • S ′ − T S'-T ST 的边一定是非匹配边,否则将使交错树扩大。
  • S S S 中的顶标 − a -a a,将 T T T 中的顶标 + a +a +a,可以发现:
    • S − T S-T ST S ′ − T ′ S'-T' ST 在相等子图中的边均无变化。
    • S − T ′ S-T' ST 的边对应顶标和减少,可能作为非匹配边加入相等子图,由上述性质,增加的边将形成增广路或使交错树扩大。
    • S ′ − T S'-T ST 的边对应顶标和增加,不可能加入相等子图。
  • slacky ( y ) = min ⁡ x ∈ S { labx ( x ) + laby ( y ) − w ( x , y ) } \text{slacky}(y) = \min\limits_{x\in S}\{\text{labx}(x) + \text{laby}(y) - w(x,y)\} slacky(y)=xSmin{labx(x)+laby(y)w(x,y)}(当且仅当 y ∈ T ′ y \in T' yT 该值才有意义),则令 a = min ⁡ y ∈ T ′ { slacky ( y ) } a = \min\limits_{y\in T'}\{\text{slacky}(y)\} a=yTmin{slacky(y)},每次修改顶标时,必定会有至少一条产生增广路或使交错树扩大的非匹配边加入相等子图。
    • 在遍历交错树的过程中,记 pre ( y ) = x ( x ∈ X , y ∈ Y ) \text{pre}(y) = x(x\in X, y\in Y) pre(y)=x(xX,yY) 表示交错树上 x , y x,y x,y 通过非匹配边相连,若产生了增广路,根据 pre \text{pre} pre 更新匹配边即可完成增广。
    • 若使交错树扩大, 更新 slacky \text{slacky} slacky,在交错树增加的结点中重复上述过程直至完成增广,由于左右部点数相同,这一过程一定能够结束。
  • 遍历交错树的部分通过 BFS \text{BFS} BFS 实现。总共需要完成 n n n 次增广,每次增广中 BFS \text{BFS} BFS 的总时间复杂度为 O ( n 2 ) \mathcal O(n^2) O(n2),更新顶标的次数为 O ( n ) \mathcal O(n) O(n)(每次更新都会使 T T T 扩大),每次更新后维护 slacky \text{slacky} slacky 并确定 a a a 的时间复杂度也为 O ( n ) \mathcal O(n) O(n),故总的时间复杂度为 O ( n 3 ) \mathcal O(n^3) O(n3)
typedef long long ll;
const int N = 405;
const int Maxn = 2e9;
int que[N], w[N][N], slacky[N];
int labx[N], laby[N], matex[N], matey[N], pre[N];
bool visx[N], visy[N];
int nl, nr, qr, n, m; ll ans;inline bool Augment(int y)
{if (matey[y]){que[++qr] = matey[y];visx[matey[y]] = visy[y] = true;return false;}else {while (y){int x = pre[y];matey[y] = x;std::swap(matex[x], y);}return true;}
}inline void bfsHungary(int src)
{for (int i = 1; i <= n; ++i){		pre[i] = 0;visx[i] = visy[i] = false;slacky[i] = Maxn;}visx[que[qr = 1] = src] = true;while (1){for (int i = 1, x; i <= qr; ++i){x = que[i];for (int y = 1; y <= n; ++y)	if (!visy[y]){int delta = labx[x] + laby[y] - w[x][y];if (delta > slacky[y])continue ;pre[y] = x;if (delta > 0)slacky[y] = delta;else if (Augment(y))return ;}}int nxt, delta = Maxn;for (int y = 1; y <= n; ++y)if (!visy[y] && slacky[y] < delta)delta = slacky[y], nxt = y;for (int i = 1; i <= n; ++i){if (visx[i])labx[i] -= delta;if (visy[i])laby[i] += delta;else slacky[i] -= delta; }qr = 0;if (Augment(nxt))return ;}
}int main()
{read(nl); read(nr); read(m);n = Max(nl, nr);int x, y, z;while (m--){read(x); read(y); read(z);CkMax(w[x][y], z);CkMax(labx[x], z);}for (int i = 1; i <= n; ++i)bfsHungary(i);for (int i = 1; i <= n; ++i) ans += w[i][matex[i]];put(ans), putchar('\n');for (int i = 1; i <= nl; ++i)put(w[i][matex[i]] ? matex[i] : 0), putchar(' ');
}

二分图稳定匹配

问题描述

  • 对于任意的 x ∈ X x \in X xX,存在一个由 Y Y Y 内所有结点构成的偏爱列表 p r f X [ x ] prf_X[x] prfX[x],列表中结点排名越靠前对 x x x 适配度越高,记 r k X [ x ] [ y ] rk_X[x][y] rkX[x][y] 表示 y y y p r f X [ x ] prf_X[x] prfX[x] 中的排名。
  • 对于任意的 y ∈ Y y\in Y yY,同样定义 p r f Y [ y ] prf_Y[y] prfY[y] r k Y [ y ] [ x ] rk_Y[y][x] rkY[y][x]
  • 对于二分图 < X , Y , E > <X,Y,E> <X,Y,E>,某一匹配是稳定的(Stable Matching)当且仅当(记 x x x 的匹配结点为 m a t X [ x ] mat_X[x] matX[x] y y y 的匹配结点为 m a t Y [ y ] mat_Y[y] matY[y]):
    • 不存在 x , y x,y x,y 满足 x ≠ m a t Y [ y ] x \not = mat_Y[y] x=matY[y],且:
      • r k X [ y ] < r k X [ m a t X [ x ] ] rk_X[y] < rk_X[mat_X[x]] rkX[y]<rkX[matX[x]]
      • r k Y [ x ] < r k Y [ m a t Y [ y ] ] rk_Y[x] < rk_Y[mat_Y[y]] rkY[x]<rkY[matY[y]]

Gale-Shapley 算法

  • 描述该算法的 python 代码如下:
rkx = rky = matx = maty = dict()
for x in prfx.keys():for i in range(len(prfx[x])):rkx[(x, prfx[x][i])] = i
for y in prfy.keys():for i in range(len(prfy[y])):rky[(y, prfy[y][i])] = ifor x in prfx.keys():prfx[x].reverse()
list = [x for x in prfx.keys()]
while len(list) > 0:x = list.pop()while len(prfx[x]) > 0:y = prfx[x].pop()if y not in maty:maty[y] = xmatx[x] = ybreak elif rky[(y, x)] < rky[(y, maty[y])]:del matx[maty[y]]list.append(maty[y])maty[y] = xmatx[x] = ybreak 
  • 关于该算法的正确性:
    • 如果 ∣ X ∣ = ∣ Y ∣ |X| = |Y| X=Y,最后总能找到一个匹配,且 p r f X [ x ] prf_X[x] prfX[x] 中的元素不会重复遍历,时间复杂度 O ( ∣ X ∣ ∣ Y ∣ ) \mathcal O(|X||Y|) O(X∣∣Y)
    • 考虑任何不在现有匹配中的 ( x , y ) (x,y) (x,y)
      • x x x 从未尝试与 y y y 匹配,则说明 r k X [ x ] [ m a t X [ x ] ] < r k X [ x ] [ y ] rk_X[x][mat_X[x]] < rk_X[x][y] rkX[x][matX[x]]<rkX[x][y]
      • x x x 尝试过与 y y y 匹配,则说明 r k Y [ y ] [ m a t Y [ y ] ] < r k Y [ y ] [ x ] rk_Y[y][mat_Y[y]] < rk_Y[y][x] rkY[y][matY[y]]<rkY[y][x]
    • 故该匹配是稳定的。
  • 定义1 配对 ( x , y ) (x,y) (x,y)有效的当且仅当存在一个稳定匹配使之包含 ( x , y ) (x,y) (x,y)
  • 定义2 y x y_x yx 表示在列表 p r f X [ x ] prf_X[x] prfX[x] 中最靠前的 y y y,一个匹配为 X X X-最优匹配当且仅当若 ( x , y x ) (x,y_x) (x,yx) 是有效的,则该匹配一定包含 ( x , y x ) (x,y_x) (x,yx)
  • 结论 Gale-Shapley 算法产生的匹配 M M M 一定为 X X X-最优匹配。

证明 y = y x y = y_x y=yx,假设 ( x , y ) (x,y) (x,y) 是有效的且 M M M 不包含 ( x , y ) (x,y) (x,y)

M M M 中与 y y y 匹配的是 x ′ x' x,由算法流程 r k Y [ y ] [ x ′ ] < r k Y [ y ] [ x ] rk_Y[y][x']<rk_Y[y][x] rkY[y][x]<rkY[y][x](要么 x x x 匹配后被 x ′ x' x 替代,要么 x ′ x' x 先匹配后无法被 x x x 替代)。

由有效配对的定义,一定存在稳定匹配 M ′ M' M 包含 ( x , y ) (x,y) (x,y)

M ′ M' M 中与 x ′ x' x 匹配的是 y ′ y' y,能够得到匹配 M M M 的条件是 r k X [ x ′ ] [ y ] < r k X [ x ′ ] [ y ′ ] rk_X[x'][y] < rk_X[x'][y'] rkX[x][y]<rkX[x][y],则由于 ( x ′ , y ) (x',y) (x,y) 的存在, M ′ M' M 是不稳定的,与假设矛盾。

图的着色

点着色

  • 设图 G G G 的点色数为 χ ( G ) \chi(G) χ(G),则显然有 χ ( G ) ≤ Δ ( G ) + 1 \chi(G) \le \Delta(G)+1 χ(G)Δ(G)+1
  • Brooks 定理 G G G 不为完全图或奇环,则 χ ( G ) ≤ Δ ( G ) \chi(G) \le \Delta(G) χ(G)Δ(G)

证明 ∣ V ( G ) ∣ = n |V(G)|=n V(G)=n,考虑数学归纳法。

首先, n ≤ 3 n\le 3 n3 时,命题显然成立。

根据归纳法,假设对于 n − 1 n - 1 n1 的命题成立。

不妨只考虑 Δ ( G ) \Delta(G) Δ(G)-正则图,因为对于非正则图来说,可以看作在正则图里删去一些边构成的,而这一过程并不会影响结论。

对于任意不是完全图也不是奇圈的正则图 G G G,任取其中一点 v v v,考虑子图 H = G − v H = G - v H=Gv,由归纳假设知 χ ( H ) ≤ Δ ( H ) ≤ Δ ( G ) \chi(H)\le \Delta(H) \le \Delta(G) χ(H)Δ(H)Δ(G),接下来我们只需证明在 H H H 中插入 v v v 不会影响结论即可。

Δ ( H ) < Δ ( G ) \Delta(H) < \Delta(G) Δ(H)<Δ(G),无需再做证明,我们只考虑 Δ ( H ) = Δ ( G ) \Delta(H) = \Delta(G) Δ(H)=Δ(G) 的情况。

Δ = Δ ( G ) \Delta = \Delta(G) Δ=Δ(G),设 H H H 染的 C C C 种颜色分别为 c 1 , c 2 , … , c Δ c_1, c_2, \dots, c_{\Delta} c1,c2,,cΔ v v v Δ \Delta Δ 个邻接点为 v 1 , v 2 , … , v Δ v_1, v_2, \dots, v_{\Delta} v1,v2,,vΔ。若 v v v 的邻接点个数不足 Δ \Delta Δ 个或存在任意两点颜色相同,同样无需再做证明。

设所有在 H H H 中染成 c i c_i ci c j c_j cj 的点以及它们之间的所有边构成子图 H i , j H_{i,j} Hi,j。不妨假设任意 2 个不同的点 v i , v j v_i,v_j vi,vj 一定在 H i , j H_{i,j} Hi,j 的同一个连通分量中,否则若在两个连通分量中的话,可以交换其中一个连通分量所有点的颜色,从而使 v i , v j v_i,v_j vi,vj 颜色相同,即能有多余的颜色对 v v v 进行染色,无需再做证明。

这里的交换颜色指的是若图中只有两种颜色 a , b a,b a,b,那么把图中原来染成颜色 a a a 的点全部染成颜色 b b b,把图中原来染成颜色 b b b 的点全部染成颜色 a a a

我们设上述连通分量为 C i , j C_{i,j} Ci,j,取出 C i , j C_{i,j} Ci,j 中一条路径记作 P i , j P_{i,j} Pi,j,则恒有 C i , j = P i , j C_{i,j} = P_{i,j} Ci,j=Pi,j。因为 v i v_i vi H H H 中的度为 Δ − 1 \Delta-1 Δ1,所以 v i v_i vi H H H 中的邻接点颜色一定两两不同,否则可以给 v i v_i vi 染别的颜色,从而和 v v v 的其他邻接点颜色重复,所以 v i v_i vi C i , j C_{i,j} Ci,j 中邻接点数量为 1。若 C i , j ≠ P i , j C_{i,j} \not = P_{i,j} Ci,j=Pi,j,设在 C i , j C_{i,j} Ci,j 中从 v i v_i vi 开始沿着 P i , j P_{i,j} Pi,j 遇到的第一个度数大于 2 的点为 u u u,注意到 u u u 的邻接点最多只用了 Δ − 2 \Delta - 2 Δ2 种颜色,所以 u u u 可以重新染色,从而使 v i , v j v_i,v_j vi,vj 不连通。

沿用这一技术,我们可以证明对于 3 个不同的点 v i , v j , v k v_i,v_j,v_k vi,vj,vk V ( C i , j ) ∩ V ( C j , k ) = { v j } V(C_{i,j})\cap V(C_{j,k}) = \{v_j\} V(Ci,j)V(Cj,k)={vj}。假设存在 w ∈ V ( C i , j ) ∩ V ( C j , k ) w \in V(C_{i,j})\cap V(C_{j,k}) wV(Ci,j)V(Cj,k),若 w ≠ v j w \not = v_j w=vj,则 w w w 必被染色为 c j c_j cj,且恰有两个被染色为 c i c_i ci 的邻接点和两个被染色为 c j c_j cj 的邻接点,注意到 w w w 的邻接点最多只用了 Δ − 2 \Delta - 2 Δ2 种颜色,所以 w w w 同样可以重新染色。

v v v 的邻接点两两相邻,则必有 Δ = n \Delta = n Δ=n,即 G G G 为完全图。否则不妨设 v 1 , v 2 v_1,v_2 v1,v2 不相邻,在 C 1 , 2 C_{1,2} C1,2 v 1 v_1 v1 的邻接点 w w w,交换 C 1 , 3 C_{1,3} C1,3 中的颜色,则 w ∈ V ( C 1 , 2 ) ∩ V ( C 2 , 3 ) w \in V(C_{1,2})\cap V(C_{2,3}) wV(C1,2)V(C2,3),与上述结论矛盾。

至此命题证明完毕。

斯坦纳树

  • 以以下题面为例,主要把握其思想:
    • 给定连通图 G G G 中的 n n n 个点与 k k k 个关键点,求能包含 k k k 个关键点的生成树的最小边权, k ≪ n k \ll n kn
  • f x , S f_{x,S} fx,S 表示以 x x x 为根且包含关键点集合 S S S 的生成树的最小边权,在外层从小到大枚举 S S S,转移分为两类:
    • f x , S = min ⁡ { f x , S , f x , S − T + f x , T } f_{x,S} = \min\{f_{x,S}, f_{x,S-T}+f_{x,T}\} fx,S=min{fx,S,fx,ST+fx,T}
    • 松弛,可通过 Dijkstra 或 SPFA 实现, f x , S = min ⁡ { f x , S , f y , S + w ( x , y ) } f_{x,S} = \min\{f_{x,S},f_{y,S} + w(x,y)\} fx,S=min{fx,S,fy,S+w(x,y)}
  • 总时间复杂度 O ( 2 k ( n + m ) log ⁡ ( n + m ) + 3 k n ) \mathcal O(2^k(n +m)\log(n + m)+3^kn) O(2k(n+m)log(n+m)+3kn)

竞赛图

  • 定义 n n n 个点的无向完全图任意定向即可得到竞赛图。
  • 性质1 竞赛图缩点后呈链状,即求出竞赛图缩点后的拓扑序后,任意两个强连通分量之间的连边一定都是从拓扑序小的连向拓扑序大的。

证明 对强连通分量个数归纳,若新增的强连通分量拓扑序最大,则所有连向其的边同向。

  • 性质2 竞赛图中每个强连通分量中存在哈密顿回路。

证明 对点数 n ( n ≥ 3 ) n(n\ge3) n(n3) 归纳,若新增的点连向原有 n n n 个点的所有边均同向,则这 n + 1 n + 1 n+1 个点不构成强连通分量,否则总可以找到 n n n 个点中的两个点,使得它们在哈密顿回路上相邻且连向新增点的方向相反。

  • 性质3 竞赛图中存在一条哈密顿路径。

证明 因为属于不同强连通分量间的点均有连边,由 性质2 取每个强连通分量中的哈密顿回路相连即可。

  • 性质4 对于点数为 n n n 的强连通竞赛图, ∀ 3 ≤ l ≤ n \forall3\le l\le n ∀3ln,其一定存在长度为 l l l 的简单环。

证明 考虑对点数 n n n 归纳,由 性质1,删除第 n n n 个点后原图变为若干个强连通分量的链状图,由归纳条件,每个强连通分量均可以构造出不超过点数的简单环,且第 n n n 个点一定有指向拓扑序最小的强连通分量的边,拓扑序最大的强连通分量一定有指向 n n n 的边,不难得到构造长度不超过 n n n 的简单环的方案。

  • 性质5 在竞赛图中若点 u u u 的出度大于等于点 v v v 的出度,则 u u u 一定可以到达 v v v

证明 考虑证明其逆否命题,由 性质1,仅需证明 u u u 所在强连通分量拓扑序大于 v v v 所在强连通分量拓扑序的情况,此时显然 v v v 的出度大于 u u u 的出度。

  • 兰道定理 将竞赛图的出度序列排序后得到 s 1 , s 2 , … , s n s_1,s_2,\dots,s_n s1,s2,,sn,该序列合法当且仅当 ∀ 2 ≤ k ≤ n , ∑ i = 1 k s i ≥ ( k 2 ) \forall 2 \le k\le n,\sum\limits_{i = 1}^{k}s_i\ge\binom{k}{2} ∀2kn,i=1ksi(2k) ∑ i = 1 n s i = ( n 2 ) \sum\limits_{i = 1}^{n}s_i = \binom{n}{2} i=1nsi=(2n)

证明 其必要性显然,因为任取点数为 k k k 的导出子图都满足该条件。考虑证明其充分性,构造一个所有边均是大点连向小点的竞赛图,则其 s i ′ = i − 1 s_i'=i-1 si=i1,上述不等式可变形为 ∑ i = 1 k s i ≥ ∑ i = 1 k s i ′ \sum\limits_{i = 1}^{k}s_i\ge \sum\limits_{i = 1}^{k}s_i' i=1ksii=1ksi,现在尝试通过不断调整该图,使得每个不等式均能取等号,每次操作如下:

  • 找到第一个 x x x 使得 s x > s x ′ s_x > s_x' sx>sx
  • x x x 后找到第一个 z z z 使得 s z < s z ′ s_z < s_z' sz<sz
  • 因而有 s z ′ > s z ≥ s x > s x ′ s_z'>s_z\ge s_x > s_x' sz>szsx>sx,即 s z ′ − s x ′ ≥ 2 s_z' - s_x'\ge 2 szsx2,此时必存在点 y y y,使得边 z → y z \to y zy y → x y \to x yx 存在,将这两条边反向,则 s z ′ s'_z sz 减少 1, s x ′ s_x' sx 增加 1, s y ′ s_y' sy 不变,原不等式仍成立。

强连通竞赛图计数

  • f n f_n fn 表示 n n n 个点的强连通竞赛图个数,考虑通过容斥原理计算 f n f_n fn,枚举拓扑序最靠前的强连通分量的大小,则剩余点连向该强连通分量的边的方向固定,而剩余点内部的连边是任意的,则对于 n ≥ 1 n \ge 1 n1,有:
    f n = 2 ( n 2 ) − ∑ i = 1 n − 1 ( n i ) f i 2 ( n − i 2 ) 2 ( n 2 ) n ! = ∑ i = 1 n f i i ! 2 ( n − i 2 ) ( n − i ) ! \begin{aligned} f_n = 2^{\binom{n}{2}}- \sum\limits_{i=1}^{n - 1}\binom{n}{i}f_{i} 2^{\binom{n - i}{2}} \\ \dfrac{2^{\binom{n}{2}}}{n!} = \sum \limits_{i = 1}^{n}\dfrac{f_i}{i!} \dfrac{2^{\binom{n - i}{2}}}{(n - i)!} \end{aligned} fn=2(2n)i=1n1(in)fi2(2ni)n!2(2n)=i=1ni!fi(ni)!2(2ni)
  • F ( x ) = ∑ n ≥ 1 f n n ! x n F(x) = \sum\limits_{n\ge 1}\dfrac{f_n}{n!} x^n F(x)=n1n!fnxn G ( x ) = ∑ n ≥ 0 2 ( n 2 ) n ! x n G(x) = \sum \limits_{n \ge 0}\dfrac{2^{\binom{n}{2}}}{n!}x^n G(x)=n0n!2(2n)xn,则上式可表达为:
    G = F G + 1 F = 1 − 1 G \begin{aligned} G = FG + 1 \\ F = 1 - \dfrac{1}{G} \\ \end{aligned} G=FG+1F=1G1
  • 通过多项式求逆计算出 F F F 即可。

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

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

相关文章

回归预测 | MATLAB实现基于SSA-KELM-Adaboost麻雀算法优化核极限学习机结合AdaBoost多输入单输出回归预测

回归预测 | MATLAB实现基于SSA-KELM-Adaboost麻雀算法优化核极限学习机结合AdaBoost多输入单输出回归预测 目录 回归预测 | MATLAB实现基于SSA-KELM-Adaboost麻雀算法优化核极限学习机结合AdaBoost多输入单输出回归预测预测效果基本介绍模型描述程序设计参考资料 预测效果 基本…

SSH远程连接MacOS catalina并进行终端颜色配置

一、开关SSH服务 在虚拟机上安装了MacOS catalina&#xff0c;想要使用SSH远程进行连接&#xff0c;但是使用“系统偏好设置”/“共享”/“远程登录”开关进行打开&#xff0c;却一直是正在启动“远程登录”&#xff1a; 难道是catalina有BUG&#xff1f;不过还是有方法的&…

第07天 Static关键字作用及用法

✅作者简介&#xff1a;大家好&#xff0c;我是Leo&#xff0c;热爱Java后端开发者&#xff0c;一个想要与大家共同进步的男人&#x1f609;&#x1f609; &#x1f34e;个人主页&#xff1a;Leo的博客 &#x1f49e;当前专栏&#xff1a;每天一个知识点 ✨特色专栏&#xff1a…

【前端|Javascript第5篇】全网最详细的JS的内置对象文章!

前言 在当今数字时代&#xff0c;前端技术正日益成为塑造用户体验的关键。我们在开发中需要用到很多js的内置对象的一些属性来帮助我们更快速的进行开发。或许你是刚踏入前端领域的小白&#xff0c;或者是希望深入了解内置对象的开发者&#xff0c;不论你的经验如何&#xff0c…

MATLAB中的代数环概念

在 Simulink 模型中&#xff0c;当存在信号环并且信号环中只存在直接馈通模块时&#xff0c;将出现代数环。直接馈通表示 Simulink 需要模块输入信号的值来计算当前时间步的输出。这种信号循环会在同一时间步中产生模块输出和输入的循环依存关系。这会导致一个需要在每个时间步…

【【verilog典型电路设计之流水线结构】】

verilog典型电路设计之流水线结构 下图是一个4位的乘法器结构&#xff0c;用verilog HDL 设计一个两级流水线加法器树4位乘法器 对于流水线结构 其实需要做的是在每级之间增加一个暂存的数据用来存储 我们得到的东西 我们一般来说会通过在每一级之间插入D触发器来保证数据的联…

OpenCV-Python中的图像处理-图像特征

OpenCV-Python中的图像处理-图像特征 图像特征Harris角点检测亚像素级精度的角点检测Shi-Tomasi角点检测SIFT(Scale-Invariant Feature Transfrom)SURF(Speeded-Up Robust Features)FAST算法BRIEF(Binary Robust Independent Elementary Features)算法ORB (Oriented FAST and R…

python编程中有哪些方便的调试方法

大家好&#xff0c;给大家分享一下一个有趣的事情&#xff0c;很多人还不知道这一点。下面详细解释一下。现在让我们来看看&#xff01; 对于每个程序开发者来说&#xff0c;调试几乎是必备技能。常用Pycharm编辑器里的方法有Print大法、log大法&#xff0c;但缺少类似Matlab的…

怎么开通Tik Tok海外娱乐公会呢?

TikTok作为全球知名的社交媒体平台&#xff0c;吸引了数亿用户的关注和参与。许多公司和个人渴望通过开通TikTok直播公会进入这一领域&#xff0c;以展示自己的创造力和吸引更多粉丝。然而&#xff0c;成为TikTok直播公会并非易事&#xff0c;需要满足一定的门槛和申请找cmxyci…

【日常积累】Linux之init系统学习

init系统简介: Linux 操作系统的启动首先从 BIOS 开始&#xff0c;接下来进入 boot loader&#xff0c;由 bootloader 载入内核&#xff0c;进行内核初始化。内核初始化的最后一步就是启动 pid 为 1 的 init 进程&#xff0c;这个进程是系统的第一个进程&#xff0c;它负责产生…

银河麒麟服务器v10 sp1 .Net6.0 上传文件错误

上一篇&#xff1a;银河麒麟服务器v10 sp1 部署.Net6.0 http https_csdn_aspnet的博客-CSDN博客 .NET 6之前&#xff0c;在Linux服务器上安装 libgdiplus 即可解决&#xff0c;libgdiplus是System.Drawing.Common原生端跨平台实现的主要提供者&#xff0c;是开源mono项目。地址…

ubuntu 部署 ChatGLM-6B 完整流程 模型量化 Nvidia

ubuntu 部署 ChatGLM-6B 完整流程 模型量化 Nvidia 初环境与设备环境准备克隆模型代码部署 ChatGLM-6B完整代码 ChatGLM-6B 是一个开源的、支持中英双语的对话语言模型&#xff0c;基于 General Language Model (GLM) 架构&#xff0c;具有 62 亿参数。结合模型量化技术&#x…

力扣 322. 零钱兑换

题目来源&#xff1a;https://leetcode.cn/problems/coin-change/description/ C题解&#xff08;来源代码随想录&#xff09;&#xff1a;题目中说每种硬币的数量是无限的&#xff0c;可以看出是典型的完全背包问题。动规五部曲分析如下&#xff1a; 确定dp数组以及下标的含义…

原码、反码、补码,进制转换,有符号数和无符号数转换

计算机底层存储数据时&#xff0c;存储的是数据对应的二进制数字。对于整型数据&#xff0c;其二进制表示形式有三种&#xff0c;分别是&#xff1a;原码、反码、补码&#xff0c;而实际存储的是整型数据的补码。 原码、反码以及补码都是有符号的&#xff0c;其中最高位存放符…

带你掌握Stable Diffution商业级玩法

课程介绍 学习地址 《Stable Diffusion商业级玩法》通过详细讲解AI绘画技巧、实操演示和个性化指导&#xff0c;帮助您从零基础成为绘画高手&#xff0c;帮助您有效推广产品或服务&#xff0c;提升市场份额。教您掌握稳定扩散绘画技巧&#xff0c;开启艺术创作新篇章。

Opencv 之ORB特征提取与匹配API简介及使用例程

Opencv 之ORB特征提取与匹配API简介及使用例程 ORB因其速度较快常被用于视觉SLAM中的位姿估计、视觉里程、图像处理中的特征提取与匹配及图像拼接等领域本文将详细给出使用例程及实现效果展示 1. API 简介 创建 static Ptr<ORB> cv::ORB::create (int nfeatures 500…

无涯教程-Perl - use函数

描述 此函数将MODULE导出的所有功能(或仅LIST引用的功能)导入当前包的名称空间。有效等效于- BEGIN { require "Module.pm"; Module->import(); }也用于在当前脚本上强加编译器指令(编译指示),尽管从本质上讲它们只是模块。 请注意,use语句在编译时进行判断。在…

springcloud3 hystrix实现服务熔断的案例配置3

一 hystrix的熔断原理 1.1 hystrix的熔断原理 在springcloud的框架里&#xff0c;熔断机制是通过hystrix实现&#xff0c;hystrix会监控服务之间的调用。当失败调用达到一定的阈值&#xff0c;默认是5s内失败20次&#xff0c;就会启用hystrix的熔断机制&#xff0c;使用命Hy…

【C++ 记忆站】缺省参数

文章目录 缺省参数的概念缺省参数的分类1、全缺省参数2、半缺省参数 缺省参数实际应用场景 缺省参数的概念 缺省参数是声明或定义函数时为函数的参数指定一个缺省值。在调用该函数时&#xff0c;如果没有指定实参则采用该形参的缺省值&#xff0c;否则使用指定的实参 正常调用一…

Docker部署ES服务,canal全量同步的时候内存爆炸,ES/Canal Adapter自动关闭,CPU100%

文章目录 问题解决方案1. 对ES的限制2. 对Canal-Adapter的限制 问题 使用canal-adapter全量同步&#xff08;参考Canal Adapter1.1.5版本API操作服务&#xff0c;手动同步数据&#xff08;4&#xff09;&#xff09;的时候 小批量数据可以正常运行&#xff08;几千条&#xf…