这个标题可能没有意义。假设如下:
- A 欠 B 5 美元
- 欠债 10 美元
- 欠 D $15
在这种基本情况下,有三个事务,但可以简化为两个事务:
- A 给 D 5 美元
- C 给 D 10 美元
给定一个更复杂的图,存在哪些算法来最小化事务总数?
在我看来,在所有交易发生后,您首先必须弄清楚每个人的涨/跌。对于您的示例,这将是:
A : -5
B : 0
C : -10
D : +15
一旦你有了它,你只需要把它们都设为零。获得最高收益,然后开始增加损失。在这一点上,它基本上是一个装箱问题。
它可能效率低下,但您可以使用整数编程。
预先计算流入/流出节点 i 的净流量,即 Fi = 总债务 + 总信用
设 M 是一个大数。
令 Yij 为决策变量,表示节点 i 支付给节点 j 的金额(有序对)。
令 Xij 为二进制变量,表示 i 和 j 之间发生了交易(无序对)
优化以下内容:
min sum_{i,j} Xij
sum_{j!=i} Yij = Fi
Yij + Yji= <= M*Xij
你可以试试贪心的方法。所以
如果 A 欠 B 钱,而 B 欠 C,则 A 欠 C 的最小值(A->B,B->C)。并且 A->B -= min(A->B, B->C)。如果在此操作之后 A->B 变为zero
然后您将其删除。循环直到您无法执行任何进一步的操作,即cycles
图中没有:
do{
bool stop = true;
G.init() // initialize some sort of edge iterator
while(edge = G.nextedge()){ //assuming nextedge will terminate after going through all edges once
foreach(outedge in edge.Dest.Outedges){ //If there's any node to 'move' the cost
minowed = min(edge.value, outedge.value)
G.edge(edge.Src, outedge.Dest).value += minowed
edge.value -= minowed
outedge.value -= minowed
if(edge.value == 0) G.remove(edge)
if(outedge.value == 0) G.remove(outedge)
stop = false
}
}
}while(!stop)
这基本上等于从图中删除任何循环以使其成为DAG
.