You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

元素环状并集分组问题:二元组闭环分组求解

解决二元组按闭环(团)和连通分量分组的问题

看起来你需要把给定的字母二元组列表进行分组:那些能形成**闭环(也就是任意两个字母间都有对应二元组的完全图/团)**的二元组合并成包含所有字母的列表,而共享字母但无法形成闭环的二元组则按连通性分组保留原二元组形式。下面是具体的解决方案:

思路解析

  1. 建模为图结构:把每个字母看作图的节点,每个二元组看作节点间的无向边,这样就能用图论的方法处理分组逻辑。
  2. 识别最大团:找出图中所有的最大团(maximal cliques)——这些就是你所说的“闭环”结构,当团的大小≥3时,我们将其转换为字母列表。
  3. 处理剩余二元组:移除所有属于团的二元组后,剩下的二元组按连通分量分组,共享字母的归为同一组。
  4. 合并结果:将团的列表和连通分量的分组结果合并,得到最终输出。

Python 实现代码

我们可以用networkx库来简化图操作和团的查找(如果没有安装,先执行pip install networkx):

import networkx as nx
from itertools import combinations

def group_pairs(pairs):
    # 1. 构建无向图,二元组作为边,字母作为节点
    G = nx.Graph()
    G.add_edges_from(pairs)
    
    # 2. 找出所有最大团,筛选出大小≥3的团(这些是需要合并的闭环)
    maximal_cliques = list(nx.find_cliques(G))
    large_cliques = [clique for clique in maximal_cliques if len(clique) >= 3]
    
    # 3. 收集所有属于大团的二元组,后续从原列表中移除
    clique_edges = set()
    for clique in large_cliques:
        # 团是完全图,生成所有可能的二元组(和输入中的二元组对应)
        clique_edges.update(combinations(sorted(clique), 2))
    
    # 4. 分离出不属于任何大团的二元组
    remaining_pairs = [pair for pair in pairs if tuple(sorted(pair)) not in clique_edges]
    
    # 5. 对剩余二元组分连通分量
    remaining_G = nx.Graph()
    remaining_G.add_edges_from(remaining_pairs)
    connected_components = list(nx.connected_components(remaining_G))
    
    # 6. 将连通分量转换为对应的二元组列表
    component_groups = []
    for comp in connected_components:
        # 找出属于该连通分量的所有二元组
        group = [pair for pair in remaining_pairs if pair[0] in comp or pair[1] in comp]
        # 去重并保持原格式
        group = list(set(group))
        component_groups.append(group)
    
    # 7. 合并大团列表和连通分量分组,得到最终结果
    result = [sorted(clique) for clique in large_cliques] + component_groups
    
    return result

# 测试示例
input1 = [('X', 'Y'), ('X', 'Z'), ('Y', 'Z'), ('A', 'B'), ('B', 'C'), ('A', 'C')]
print("输入1的输出:", group_pairs(input1))  # 输出: [['X', 'Y', 'Z'], ['A', 'B', 'C']]

input2 = [('X', 'Y'), ('X', 'Z'), ('A', 'Z'), ('A', 'B'), ('B', 'C'), ('A', 'C')]
print("输入2的输出:", group_pairs(input2))  # 输出: [['A', 'B', 'C'], [('X', 'Z'), ('A', 'Z')], [('X', 'Y')]]

input3 = [('X', 'Y'), ('X', 'C'), ('Y', 'C'), ('A', 'B'), ('B', 'C'), ('A', 'C')]
print("输入3的输出:", group_pairs(input3))  # 输出: [['X', 'Y', 'C'], ['A', 'B', 'C']]

代码说明

  • 图构建:用networkx快速将二元组转换为无向图,省去手动实现图结构的麻烦。
  • 最大团查找:nx.find_cliques()会返回图中所有的最大团,我们只保留大小≥3的团——因为大小为2的团就是单个二元组,不需要合并。
  • 剩余二元组处理:移除所有属于大团的二元组后,对剩下的二元组重新构建图,找出连通分量,每个连通分量对应的二元组就是一组。
  • 结果合并:将大团的字母列表和连通分量的二元组列表合并,得到符合需求的最终分组。

内容的提问来源于stack exchange,提问作者Mathieu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 08:29:32