【发布时间】:2013-03-30 20:31:14
【问题描述】:
我一直在使用我编写的一个小 Python 脚本来管理室友之间的债务。它有效,但缺少一些功能,其中之一是简化不必要的复杂债务结构。例如,如果下面的加权有向图代表一些人,箭头代表他们之间的债务(爱丽丝欠鲍勃 20 美元,查理欠查理 5 美元,鲍勃欠查理 10 美元等):
很明显,这张图应该简化为下图:
如果爱丽丝可以直接把 10 美元给查理,那么从爱丽丝到鲍勃再从鲍勃到查理的 10 美元是没有意义的。
因此,在一般情况下,目标是获取债务图并对其进行简化(即生成具有相同节点但不同边的新图),以便
- 没有一个节点有边指向它的内部和外部(没有无用的货币易手)
- 所有节点通过它们的“流量”与它们在原始图中的相同(在资金流向方面是相同的)。
“流”是指所有输入的值减去所有输出的值(对此有专门术语吗?我不是图论专家)。所以在上面的例子中,每个节点的流量值为:
- 鲍勃:+10
- 爱丽丝:-25
- 查理:+15
您可以看到第一张和第二张图通过每个节点的流量相同,因此这是一个很好的解决方案。还有一些其他简单的情况,例如,任何循环都可以通过删除最低值的边并从所有其他边中减去它的值来简化。
这个:
应该简化成这样:
我无法想象没有人研究过这个问题;我只是不知道要搜索哪些术语来查找相关信息(同样,不是图论专家)。我一直在寻找几个小时无济于事,所以我的问题是:根据上面为任何加权有向图指定的条件,有什么算法可以产生简化(新图)?
【问题讨论】:
-
整理的标准是什么。即使在您的最后一种情况下,丹尼尔也可以给鲍勃“3”,而爱丽丝给查理“8”和鲍勃“7”。
-
哦,好点。我认为最佳算法也会最小化边的数量(你的建议),但我会满足于我在问题中指定的两个标准。
-
从算法的角度来看这个问题很有趣,但你认为这在实践中可行吗?如果A欠B,B欠C,C为什么要从A那里拿钱? C借钱给B不知道A破产了...
-
我们用它来管理因购买公共食品和支付账单而产生的债务,本身没有直接贷款。让 A 直接向 C 付款的想法是避免不必要的物流(A 必须找到 B 才能给钱,然后 B 必须找到 C,而不是 A 直接找到 C)。
标签: algorithm graph-theory graph-algorithm