Use this to learn the idea, then write your own version.
123 4import heapq5 6 78class Solution(object):9 def minMoves(self, balance):10 """11 :type balance: List[int]12 :rtype: int13 """14 def clamp(x, l, r):15 return min(max(x, l), r)16 17 def cost(i):18 result = prefix = 019 max_heap = []20 for j in xrange(len(balance)):21 prefix += balance[(i+j)%len(balance)]22 c = clamp(prefix, 0, total)23 result += abs(prefix-c)24 25 heapq.heappush(max_heap, -c)26 if -max_heap[0] > c:27 result += -heapq.heappop(max_heap)-c28 heapq.heappush(max_heap, -c)29 return result30 31 total = sum(balance)32 return min(cost(i) for i in xrange(len(balance))) if total >= 0 else -133 34 35363738import heapq39 40 41424344INF = float("inf")45class Edge(object):46 def __init__(self, from_node, to, rev, cap, cost, flow):47 self.from_node = from_node48 self.to = to49 self.rev = rev50 self.cap = cap51 self.cost = cost52 self.flow = flow53 54 55class MCMF(object):56 def __init__(self, n):57 self.N = n58 self.ed = [[] for _ in xrange(n)]59 self.seen = [0]*n60 self.dist = [INF]*n61 self.pi = [0]*n62 self.par = [None]*n63 64 def addEdge(self, from_node, to, cap, cost):65 if from_node == to:66 return67 self.ed[from_node].append(Edge(from_node, to, len(self.ed[to]), cap, cost, 0))68 self.ed[to].append(Edge(to, from_node, len(self.ed[from_node])-1, 0, -cost, 0))69 70 def path(self, s):71 self.seen = [0]*self.N72 self.dist = [INF]*self.N73 self.par = [None]*self.N74 self.dist[s] = 075 q = [(0, s)]76 while q:77 d, u = heapq.heappop(q)78 if d != self.dist[u]:79 continue80 self.seen[u] = 181 for edge in self.ed[u]:82 if edge.cap-edge.flow <= 0:83 continue84 val = d+self.pi[u]-self.pi[edge.to]+edge.cost85 if val < self.dist[edge.to]:86 self.dist[edge.to] = val87 self.par[edge.to] = edge88 heapq.heappush(q, (val, edge.to))89 for i in xrange(self.N):90 if self.dist[i] != INF:91 self.pi[i] += self.dist[i]92 93 def maxflow(self, s, t):94 total_flow = total_cost = 095 while True:96 self.path(s)97 if not self.seen[t]:98 break99 flow = INF100 edge = self.par[t]101 while edge:102 flow = min(flow, edge.cap-edge.flow)103 edge = self.par[edge.from_node]104 total_flow += flow105 edge = self.par[t]106 while edge:107 edge.flow += flow108 self.ed[edge.to][edge.rev].flow -= flow109 edge = self.par[edge.from_node]110 for edges in self.ed:111 for edge in edges:112 total_cost += edge.cost*edge.flow113 return total_flow, total_cost2114 115 116class Solution2(object):117 def minMoves(self, balance):118 """119 :type balance: List[int]120 :rtype: int121 """122 if sum(balance) < 0:123 return -1124 source, sink = len(balance), len(balance)+1125 mcmf = MCMF(len(balance)+2)126 for i in xrange(len(balance)):127 mcmf.addEdge(i, (i+1)%len(balance), INF, 1)128 mcmf.addEdge((i+1)%len(balance), i, INF, 1)129 demand = 0130 for i in xrange(len(balance)):131 if balance[i] > 0:132 mcmf.addEdge(source, i, balance[i], 0)133 elif balance[i] < 0:134 mcmf.addEdge(i, sink, -balance[i], 0)135 demand += -balance[i]136 flow, cost = mcmf.maxflow(source, sink)137 return cost if flow == demand else -1138