Inclusion Exclusion Principle

本文介绍了组合数学中的包含排除原理,该原理用于计算有限集合的并集元素数量。文章提供了一个例子,解释了如何使用该原理来计算在特定范围内与给定数互质的整数的数量。给出了输入输出格式,并指出这是一个应用包含排除原理解决的问题。

Inclusion-Exclusion Principle

See the complete article on my own blog https://dyingdown.github.io/2019/08/15/Inclusion-Exclusion-Principle/

In combinatorics (combinatorial mathematics), the inclusion–exclusion principle is a counting technique which generalizes the familiar method of obtaining the number of elements in the union of two finite sets; – From Wikipedia

[外链图片转存失败(img-i1D8ihUF-1567835680066)(https://upload.wikimedia.org/wikipedia/commons/thumb/4/42/Inclusion-exclusion.svg/220px-Inclusion-exclusion.svg.png)]

Example: Set A and B
∣ A ∪ B ∣ = ∣ A ∣ + ∣ B ∣ − ∣ A ∩ B ∣ |A \cup B| = |A|+|B|-|A \cap B| AB=A+BAB
Set A, B and C
∣ A ∪ B ∪ C ∣ = ∣ A ∣ + ∣ B ∣ + ∣ C ∣ − ∣ A ∩ B ∣ − ∣ A ∩ C ∣ − ∣ B ∩ C ∣ + ∣ A ∩ B ∩ C ∣ |A \cup B \cup C| = |A| + |B| + |C| -|A \cap B| - |A \cap C| - |B \cap C| + |A \cap B \cap C| AB

import networkx as nx import sys from gamma_fun import gamma_plus_set, gamma_plus sys.setrecursionlimit(3000) # 将默认的递归深度修改为3000 def MCsAlgorithm(S, C_s, G, s, t, all_min_cuts): """ 递归枚举所有最小割集 参数: G: 原始图 S: 初始化当前只包含s的节点集合 C_s: 当前割集C_s,包含s和网络其他节点的连接边 s: 源节点 t: 目标节点 all_min_cuts: 存储所有找到的最小割集 """ # 计算 Γ+(𝑆) = Γ(S) - S gamma_plus_S = gamma_plus_set(G, S) # Γ+(𝑆)\{t},在Γ+(𝑆)中移除目标节点t(如果存在) if t in gamma_plus_S: gamma_plus_S.remove(t) # 如果 Γ⁺(S) \ {t} ≠ ∅ if gamma_plus_S: # 对于每个外部邻居v(除了t),v∈Γ+(𝑆)\{t} for v in gamma_plus_S: # 创建不包含S集合和v的子图:G'= (V\S)\{v},即从原图中移除S集合的所有节点和节点v nodes_to_remove = S.copy() nodes_to_remove.add(v) subgraph_nodes = set(G.nodes()) - nodes_to_remove # 检查子图是否为空或只有一个节点 if len(subgraph_nodes) == 0: # 空图被认为是连通的(根据定义1:孤立节点被视为一个分量) is_connected_subgraph = True elif len(subgraph_nodes) == 1: # 单节点图总是连通的 is_connected_subgraph = True else: # 对于有多个节点的子图,检查连通性 subgraph = G.subgraph(subgraph_nodes) # 创建不包含S集合和v的子图 is_connected_subgraph = nx.is_connected(subgraph) gamma_plus_v = gamma_plus(G, v) # 检查子图是否连通(定义1的要求) if is_connected_subgraph: # 计算新的割集 C_v # 1. 复制当前割集 C_v = set(C_s) # 2. 添加: {(v,w) ∈ E : w ∈ Γ⁺(S)} for w in gamma_plus_S: if G.has_edge(v, w): C_v.add(frozenset({v, w})) # 3. 添加: {(v,w) ∈ E : w ∈ Γ⁺(v)} for w in gamma_plus_v: C_v.add(frozenset({v, w})) # 4. 移除: {(w,v) ∈ E : w ∈ S} for w in S: if G.has_edge(w, v): edge = frozenset({w, v}) if edge in C_v: C_v.remove(edge) # 输出新的割集 if C_v not in all_min_cuts: all_min_cuts.append(C_v) print(f"Found MC: {C_v}") # 更新 S: S = S ∪ Γ⁺(v) new_S = S | gamma_plus_v MCsAlgorithm(new_S, C_v, G, s, t, all_min_cuts) def find_all_minimal_cutsets(G, s, t): """ 枚举图G中所有s-t最小割集 参数: G: 无向图 s: 源节点 t: 目标节点 返回: 最小割集的列表 """ # 初始化 S = {s} all_min_cuts = [] # 计算初始割集 C_s = {(v,w) ∈ E : v ∈ S, w ∈ Γ⁺(S)} C_s = set() for node in S: # v ∈ S neighbors = set(G.neighbors(node)) # v的邻节点集合 external_neighbors = neighbors - S # Γ⁺(S) for w in external_neighbors: # w ∈ Γ⁺(S) if G.has_edge(node, w): # (v,w) edge = frozenset({node, w}) C_s.add(edge) print(f"Initial cut C_s: {C_s}") all_min_cuts.append(C_s.copy()) # 开始递归算法 MCsAlgorithm(S, C_s, G, s, t, all_min_cuts) return all_min_cuts
09-18
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值