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

如何求解最小权重的单射/满射映射及对应的Python实现?

二分图最小权重映射求解方案

问题前提

给定对应完全二分图$K_{m,n}$边权重的$m \times n$矩阵w,需求是找到从集合${1,…,m}$到${1,…,n}$的最小权重映射,映射要求为单射或满射。映射的规则等价于为${1,…,m}$中的每个顶点$v$,恰好选取一条与$v$关联的边。

m≤n场景:最小权重单射求解

该场景下最小权重单射等价于二分图的最小权完美匹配,可直接调用scipy的linear_sum_assignment接口实现,示例代码如下:

import numpy as np
import scipy.optimize

# 示例:m=5,n=10,生成随机权重矩阵
w = np.random.rand(5, 10)
# 返回值分别为左边节点索引数组、匹配到的右边节点索引数组
left_ind, right_ind = scipy.optimize.linear_sum_assignment(w)
print("匹配结果:", list(zip(left_ind, right_ind)))
print("总权重:", w[left_ind, right_ind].sum())

m≥n场景:最小权重满射求解

实现思路

满射要求右边n个节点每个至少被匹配一次,我们可以通过构造扩展权重矩阵的方式,将问题转化为标准的最小权完美匹配问题,复用linear_sum_assignment接口求解:

  • 将右边的n个节点重复复制,直到右边总节点数等于左边的m个,生成m×m的扩展权重矩阵,扩展位置的权重和原对应节点的权重一致
  • 对扩展矩阵调用最小权完美匹配算法
  • 将匹配得到的扩展右边节点索引映射回原始的n个节点编号,得到最终满射结果

完整实现代码

import numpy as np
import scipy.optimize

def min_weight_surjection(w):
    m, n = w.shape
    assert m >= n, "该方法仅适用于m≥n的满射求解场景"
    # 构造m*m的扩展权重矩阵
    extended_w = np.tile(w, (1, (m // n) + 1))[:, :m]
    # 求解扩展矩阵的最小权完美匹配
    left_ind, extended_right_ind = scipy.optimize.linear_sum_assignment(extended_w)
    # 映射回原始右边节点编号
    right_ind = extended_right_ind % n
    return left_ind, right_ind, w[left_ind, right_ind].sum()

# 测试示例
if __name__ == "__main__":
    # 示例:m=5,n=3,生成随机权重矩阵
    w = np.random.rand(5, 3)
    left_ind, right_ind, total_weight = min_weight_surjection(w)
    print("左边节点索引:", left_ind)
    print("匹配的右边节点索引:", right_ind)
    print("是否满足满射(右边所有节点都出现):", set(right_ind) == set(range(3)))
    print("总权重:", total_weight)

结果说明

返回的right_ind数组长度和左边节点数m一致,每个元素对应左边节点匹配的右边节点编号,保证右边所有n个节点都至少出现一次,且总权重为所有满足满射的映射中的最小值。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 18:15:05