Skip to content

Instantly share code, notes, and snippets.

@knuu
Created October 18, 2016 16:59
Show Gist options
  • Save knuu/f21d2c633644c2c0096f741a1815d360 to your computer and use it in GitHub Desktop.
Save knuu/f21d2c633644c2c0096f741a1815d360 to your computer and use it in GitHub Desktop.
京都大学プログラミングコンテスト 2016 E. 柵
import sys
import collections
if sys.version[0] == '2':
range, input = xrange, raw_input
class MaxFlow:
"""Dinic Algorithm: find max-flow
complexity: O(EV^2)
used in GRL6A(AOJ)
"""
class Edge:
def __init__(self, to, rev, cap):
self.to, self.cap, self.rev = to, cap, rev
def __init__(self, V):
""" V: the number of vertexes
E: adjacency list
source: start point
sink: goal point
"""
self.V = V
self.E = [[] for _ in range(V)]
def add_edge(self, fr, to, cap):
self.E[fr].append(self.Edge(to, len(self.E[to]), cap))
self.E[to].append(self.Edge(fr, len(self.E[fr])-1, 0))
def dinic(self, source, sink):
"""find max-flow"""
INF = float('inf')
maxflow = 0
while True:
self.bfs(source)
if self.level[sink] < 0:
return maxflow
self.itr = [0] * self.V
while True:
flow = self.dfs(source, sink, INF)
if flow > 0:
maxflow += flow
else:
break
def dfs(self, vertex, sink, flow):
"""find augmenting path"""
if vertex == sink:
return flow
for i in range(self.itr[vertex], len(self.E[vertex])):
self.itr[vertex] = i
e = self.E[vertex][i]
if e.cap > 0 and self.level[vertex] < self.level[e.to]:
d = self.dfs(e.to, sink, min(flow, e.cap))
if d > 0:
e.cap -= d
self.E[e.to][e.rev].cap += d
return d
return 0
def bfs(self, start):
"""find shortest path from start"""
que = collections.deque()
self.level = [-1] * self.V
que.append(start)
self.level[start] = 0
while que:
fr = que.popleft()
for e in self.E[fr]:
if e.cap > 0 and self.level[e.to] < 0:
self.level[e.to] = self.level[fr] + 1
que.append(e.to)
H, W = map(int, input().split())
board = [input() for _ in range(H)]
V = 2 * H * W + 2
mf = MaxFlow(V)
source, sink = V-2, V-1
drc = [(-1, 0), (0, 1), (1, 0), (0, -1)]
for r, row in enumerate(board):
for c, col in enumerate(row):
mf.add_edge(H*W+r*W+c, r*W+c, 1)
if col == 'X':
mf.add_edge(source, r*W+c, float('inf'))
for dr, dc in drc:
nr, nc = r+dr, c+dc
if 0 <= nr < H and 0 <= nc < W:
mf.add_edge(r*W+c, H*W+nr*W+nc, float('inf'))
else:
mf.add_edge(r*W+c, sink, float('inf'))
ans = mf.dinic(source, sink)
print(-1 if ans == float('inf') else ans)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment