Problem:


Score : 800 points

Problem Statement

There is a pond with a rectangular shape.
The pond is divided into a grid with H rows and W columns of squares.
We will denote the square at the i-th row from the top and j-th column from the left by (i,\ j).

Some of the squares in the pond contains a lotus leaf floating on the water.
On one of those leaves, S, there is a frog trying to get to another leaf T.
The state of square (i,\ j) is given to you by a character a_{ij}, as follows:

. : A square without a leaf.

o : A square with a leaf floating on the water.

S : A square with the leaf S.

T : A square with the leaf T.

The frog will repeatedly perform the following action to get to the leaf T: "jump to a leaf that is in the same row or the same column as the leaf where the frog is currently located."

Snuke is trying to remove some of the leaves, other than S and T, so that the frog cannot get to the leaf T.
Determine whether this objective is achievable. If it is achievable, find the minimum necessary number of leaves to remove.

Constraints

2 ≤ H, W ≤ 100

a_{ij} is ., o, S or T.

There is exactly one S among a_{ij}.

There is exactly one T among a_{ij}.

Input

Input is given from Standard Input in the following format:

H W
a_{11} ... a_{1W}
:
a_{H1} ... a_{HW}

Output

If the objective is achievable, print the minimum necessary number of leaves to remove.
Otherwise, print -1 instead.

Sample Input 1

3 3
S.o
.o.
o.T

Sample Output 1

2

Remove the upper-right and lower-left leaves.

Sample Input 2

3 4
S...
.oo.
...T

Sample Output 2

0

Sample Input 3

4 3
.S.
.o.
.o.
.T.

Sample Output 3

-1

Sample Input 4

10 10
.o...o..o.
....o.....
....oo.oo.
..oooo..o.
....oo....
..o..o....
o..o....So
o....T....
....o.....
........oo

Sample Output 4

5



Sample input:
3 3
S.o
.o.
o.T


Sample output:
2

Submission status: Accepted

Solution code:
def main():
    import sys
    input = sys.stdin.readline
    from collections import deque

    class Dinic:
        def __init__(self, N):
            self.N = N
            self.G = [[] for i in range(N)]

        def add_edge(self, fr, to, cap):
            forward = [to, cap, None]
            forward[2] = backward = [fr, 0, forward]
            self.G[fr].append(forward)
            self.G[to].append(backward)

        def add_multi_edge(self, v1, v2, cap1, cap2):
            edge1 = [v2, cap1, None]
            edge1[2] = edge2 = [v1, cap2, edge1]
            self.G[v1].append(edge1)
            self.G[v2].append(edge2)

        def bfs(self, s, t):
            self.level = level = [None] * self.N
            deq = deque([s])
            level[s] = 0
            G = self.G
            while deq:
                v = deq.popleft()
                lv = level[v] + 1
                for w, cap, _ in G[v]:
                    if cap and level[w] is None:
                        level[w] = lv
                        deq.append(w)
            return level[t] is not None

        def dfs(self, v, t, f):
            if v == t:
                return f
            level = self.level
            for e in self.it[v]:
                w, cap, rev = e
                if cap and level[v] < level[w]:
                    d = self.dfs(w, t, min(f, cap))
                    if d:
                        e[1] -= d
                        rev[1] += d
                        return d
            return 0

        def flow(self, s, t):
            flow = 0
            INF = 10 ** 9 + 7
            G = self.G
            while self.bfs(s, t):
                *self.it, = map(iter, self.G)
                f = INF
                while f:
                    f = self.dfs(s, t, INF)
                    flow += f
            return flow

    H, W = map(int, input().split())
    grid = []
    for _ in range(H):
        line = input().rstrip('\n')
        grid.append(line)

    dinic = Dinic(H+W+5)
    for h in range(H):
        for w in range(W):
            if grid[h][w] == 'o':
                dinic.add_edge(h+1, H+w+1, 1)
                dinic.add_edge(H+w+1, h+1, 1)
            elif grid[h][w] == 'S':
                dinic.add_edge(H+W+1, h+1, 10**5)
                dinic.add_edge(H+W+1, H+w+1, 10**5)
            elif grid[h][w] == 'T':
                dinic.add_edge(h+1, H+W+2, 10**5)
                dinic.add_edge(H+w+1, H+W+2, 10**5)

    ans = dinic.flow(H+W+1, H+W+2)
    if ans > 400:
        print(-1)
    else:
        print(ans)


if __name__ == '__main__':
    main()

Submission status: Accepted

Solution code:
"""
.o...o..o.
....o.....
....oo.oo.
..oooo..o.
....oo....
..o..o....
o..o....So
o....T....
....o.....
........oo

グラフを作る
⇛ SからTにたどり着く個数を全探索
⇛ たどり着く直前の座標を保持
⇛ 直前のバリエーション
解説AC
⇛ 行内、列内は自由に動ける
⇛ 行/列のどこかにいる状態でもたせる
⇛ 点の上は行⇔列の切り替えが出来るので、cap==1とする
⇛ 結局MaxCutをしているのと一緒！！
"""

from collections import deque
from collections import defaultdict
import sys
sys.setrecursionlimit(100000)
class Dinic:
    def __init__(self):
        # self.N = N
        self.G = defaultdict(list)
    
    def add_edge(self, fr, to, cap):
        """
        :param fr: 始点
        :param to: 終点
        :param cap: 容量
        """
        # forwardの最後には、キャパのうちどれだけ使ったかが入る
        forward = [to, cap, None]
        backward = [fr, 0, forward]
        forward[-1] = backward
        self.G[fr].append(forward)
        self.G[to].append(backward)

    def add_multi_edge(self, v1, v2, cap1, cap2):
        """
        :param v1: 始点
        :param v2: 終点
        :param cap1: 容量1
        :param cap2: 容量2
        """
        edge1 = [v2, cap1, None]
        edge2 = [v1, cap2, edge1]
        edge1[-1] = edge2
        self.G[v1].append(edge1)
        self.G[v2].append(edge2)

    def bfs(self, s, t):
        """
        :param s: bfsの始点(source)
        :param t: bfsの終点(sink)
        :return: tに到達したかどうか。(sourceからの距離を保存しながら)
        """
        self.level = level = defaultdict(int)
        q = deque([s])
        level[s] = 1
        G = self.G
        while len(q) > 0:
            v = q.popleft()
            lv = level[v] + 1
            nexts = G[v]
            for w, cap, _ in nexts:
                if cap > 0 and level[w] == 0:
                    level[w] = lv
                    q.append(w)
        is_reach = (level[t] > 0)
        return is_reach

    def dfs(self, v, t, f):
        """
        :param v: 点v
        :param t: 終点(sink)
        :param f: v時点でのフロー
        :return: 終点到達時のフローを返す
        """   
        if v == t:
            return f
        level = self.level
        nexts = self.G[v]
        for edge in nexts:
            w, cap, rev = edge
            # まだキャパがあるならば
            if cap > 0 and level[v] < level[w]:
                # キャパが余ってるなら全部流すし
                # カツカツならキャパのmaxまで流す
                d = self.dfs(w, t, min(f, cap))
                # 帰りがけに、更新
                if d > 0:
                    # 順方向のキャパをd下げる
                    # 逆方向のキャパをd増やす
                    edge[1] -= d
                    rev[1] += d
                    return d
        # 次の道が見つからなければ終了
        return 0
    
    def flow(self, s, t):
        """
        :param s: 始点
        :param t: 終点
        :return : 最大フロー
        """
        flow = 0
        INF = 10**10
        G = self.G
        # ルートが存在する限り、続ける
        while self.bfs(s, t):
            f = INF
            while f > 0:
                f = self.dfs(s, t, INF)
                flow += f
        return flow



ans = set()
H, W = map(int, input().split())
fields = []
for i in range(H):
    inp = list(input())
    fields.append(inp)
dinic = Dinic()
start = -1
end = -2
INF = 10**10
for i in range(H):
    for j in range(W):
        if fields[i][j] == "T":
            dinic.add_edge(i,end,INF)
            dinic.add_edge(j+H,end,INF)
        if fields[i][j] == "S":
            dinic.add_edge(start,i,INF)
            dinic.add_edge(start,j+H,INF)
        if fields[i][j] != ".":
            dinic.add_edge(i,j+H,1)
            dinic.add_edge(j+H,i,1)

ans = dinic.flow(start,end)
if ans > INF:print(-1)
else:print(ans)

Submission status: Accepted

Solution code:
# -*- coding: utf-8 -*-

import sys

def input(): return sys.stdin.readline().strip()
def list2d(a, b, c): return [[c] * b for i in range(a)]
def list3d(a, b, c, d): return [[[d] * c for j in range(b)] for i in range(a)]
def list4d(a, b, c, d, e): return [[[[e] * d for j in range(c)] for j in range(b)] for i in range(a)]
def ceil(x, y=1): return int(-(-x // y))
def INT(): return int(input())
def MAP(): return map(int, input().split())
def LIST(N=None): return list(MAP()) if N is None else [INT() for i in range(N)]
def Yes(): print('Yes')
def No(): print('No')
def YES(): print('YES')
def NO(): print('NO')
sys.setrecursionlimit(10 ** 9)
INF = 10 ** 18
MOD = 10 ** 9 + 7

class Dinic:
    """ 最大流(Dinic) """

    def __init__(self, n):
        self.n = n
        self.links = [[] for _ in range(n)]
        self.depth = None
        self.progress = None
 
    def add_link(self, _from, to, cap):
        self.links[_from].append([cap, to, len(self.links[to])])
        self.links[to].append([0, _from, len(self.links[_from]) - 1])
 
    def bfs(self, s):
        from collections import deque

        depth = [-1] * self.n
        depth[s] = 0
        q = deque([s])
        while q:
            v = q.popleft()
            for cap, to, _ in self.links[v]:
                if cap > 0 and depth[to] < 0:
                    depth[to] = depth[v] + 1
                    q.append(to)
        self.depth = depth
 
    def dfs(self, v, t, flow):
        if v == t:
            return flow
        links_v = self.links[v]
        for i in range(self.progress[v], len(links_v)):
            self.progress[v] = i
            cap, to, rev = link = links_v[i]
            if cap == 0 or self.depth[v] >= self.depth[to]:
                continue
            d = self.dfs(to, t, min(flow, cap))
            if d == 0:
                continue
            link[0] -= d
            self.links[to][rev][0] += d
            return d
        return 0
 
    def max_flow(self, s, t):
        flow = 0
        while True:
            self.bfs(s)
            if self.depth[t] < 0:
                return flow
            self.progress = [0] * self.n
            current_flow = self.dfs(s, t, INF)
            while current_flow > 0:
                flow += current_flow
                current_flow = self.dfs(s, t, INF)

def build_grid(H, W, intv, _type, space=True, padding=False):
    # 入力がスペース区切りかどうか
    if space:
        _input = lambda: input().split()
    else:
        _input = lambda: input()
    _list = lambda: list(map(_type, _input()))
    # 余白の有無
    if padding:
        offset = 1
    else:
        offset = 0
    grid = list2d(H+offset*2, W+offset*2, intv)
    for i in range(offset, H+offset):
        row = _list()
        for j in range(offset, W+offset):
            grid[i][j] = row[j-offset]
    return grid

H, W = MAP()
grid = build_grid(H, W, '', str, space=0)

# 最大流：頂点は各行全体、各列全体、始点、終点
dn = Dinic(H+W+2)
s = H + W
t = H + W + 1
for i in range(H):
    for j in range(W):
        if grid[i][j] == 'o':
            dn.add_link(i, H+j, 1)
            dn.add_link(H+j, i, 1)
        elif grid[i][j] == 'S':
            dn.add_link(s, i, INF)
            dn.add_link(s, H+j, INF)
        elif grid[i][j] == 'T':
            dn.add_link(i, t, INF)
            dn.add_link(H+j, t, INF)

ans = dn.max_flow(s, t)
if ans >= INF:
    print(-1)
else:
    print(ans)

Submission status: Accepted

Solution code:
# Dinic's algorithm
from collections import deque
class Dinic:
    def __init__(self, N):
        self.N = N
        self.G = [[] for i in range(N)]

    def add_edge(self, fr, to, cap):
        forward = [to, cap, None]#(行き先、容量、逆辺の参照)
        forward[2] = backward = [fr, 0, forward]
        self.G[fr].append(forward)
        self.G[to].append(backward)

    def add_multi_edge(self, v1, v2, cap1, cap2):
        edge1 = [v2, cap1, None]
        edge1[2] = edge2 = [v1, cap2, edge1]
        self.G[v1].append(edge1)
        self.G[v2].append(edge2)

    def bfs(self, s, t):
        self.level = level = [None]*self.N
        deq = deque([s])
        level[s] = 0
        G = self.G
        while deq:
            v = deq.popleft()
            lv = level[v] + 1
            for w, cap, _ in G[v]:
                if cap and level[w] is None:
                    level[w] = lv
                    deq.append(w)
        return level[t] is not None

    def dfs(self, v, t, f):
        if v == t:
            return f
        level = self.level
        for e in self.it[v]:
            w, cap, rev = e
            if cap and level[v] < level[w]:
                d = self.dfs(w, t, min(f, cap))
                if d:
                    e[1] -= d
                    rev[1] += d
                    return d
        return 0

    def flow(self, s, t):
        flow = 0
        INF = 10**10
        G = self.G
        while self.bfs(s, t):
            *self.it, = map(iter, self.G)
            f = INF
            while f:
                f = self.dfs(s, t, INF)
                flow += f
        return flow
inf = 10**9
H, W = map(int, input().split())
a = [list(input()) for _ in range(H)]
D = Dinic(H+W+2)
for i in range(H):
    for j in range(W):
        if a[i][j] == 'S':
            D.add_edge(0, i+1, inf)
            D.add_edge(0, j+1+H, inf)
        elif a[i][j] == 'T':
            D.add_edge(i+1, H+W+1, inf)
            D.add_edge(j+1+H, H+W+1, inf)
        elif a[i][j] == 'o':
            D.add_edge(i+1, j+1+H, 1)
            D.add_edge(j+1+H, i+1, 1)
ans = D.flow(0, H+W+1)
print(ans if ans<inf else -1)

Submission status: Accepted

Solution code:
import sys
read = sys.stdin.buffer.read
readline = sys.stdin.buffer.readline
readlines = sys.stdin.buffer.readlines

from collections import deque

H,W = map(int,readline().split())
A = [line.rstrip().decode('utf-8') for line in readlines()]

class Dinic:
    def __init__(self, N, source, sink):
        self.N = N
        self.G = [[] for _ in range(N)]
        self.source = source
        self.sink = sink

    def add_edge(self, fr, to, cap):
        n1 = len(self.G[fr])
        n2 = len(self.G[to])
        self.G[fr].append([to, cap, n2])
        self.G[to].append([fr, 0, n1]) # 逆辺を cap 0 で追加
        
    def add_edge_undirected(self, fr, to, cap):
        n1 = len(self.G[fr])
        n2 = len(self.G[to])
        self.G[fr].append([to, cap, n2])
        self.G[to].append([fr, cap, n1]) # 逆辺を cap 0 で追加
        
    def bfs(self):
        level = [0] * self.N
        G = self.G; source = self.source; sink = self.sink
        q = deque([source])
        level[source] = 1
        pop = q.popleft; append = q.append
        while q:
            v = pop()
            lv = level[v] + 1
            for to, cap, rev in G[v]:
                if not cap:
                    continue
                if level[to]:
                    continue
                level[to] = lv
                if to == sink:
                    self.level = level
                    return
                append(to)
        self.level = level
        
    def dfs(self,v,f):
        if v == self.sink:
            return f
        G = self.G
        prog = self.progress
        level = self.level
        lv = level[v]
        E = G[v]
        for i in range(prog[v],len(E)):
            to, cap, rev = E[i]
            prog[v] = i
            if not cap:
                continue
            if level[to] <= lv:
                continue
            x = f if f < cap else cap
            ff = self.dfs(to, x)
            if ff:
                E[i][1] -= ff
                G[to][rev][1] += ff
                return ff
        return 0
    
    def max_flow(self):
        INF = 10**18
        flow = 0
        while True:
            self.bfs()
            if not self.level[self.sink]:
                return flow
            self.progress = [0] * self.N
            while True:
                f = self.dfs(self.source, INF)
                if not f:
                    break
                flow += f
        return flow

source = 0
sink = H+W+1

dinic = Dinic(H+W+2, source, sink)
add = dinic.add_edge_undirected

INF = 10 ** 18
for h in range(1,H+1):
    for w,ox in enumerate(A[h-1],1):
        if ox == 'x':
            continue
        elif ox == 'o':
            add(h,H+w,1)
        elif ox == 'S':
            add(source,h,INF)
            add(source,H+w,INF)
        elif ox == 'T':
            add(sink,h,INF)
            add(sink,H+w,INF)

f = dinic.max_flow()
answer = f if f < INF else -1
print(answer)

Submission status: Accepted

Solution code:
import sys
read = sys.stdin.buffer.read
readline = sys.stdin.buffer.readline
readlines = sys.stdin.buffer.readlines

from collections import deque

H,W = map(int,readline().split())
A = [line.rstrip().decode('utf-8') for line in readlines()]

class Dinic:
    def __init__(self, N, source, sink):
        self.N = N
        self.G = [[] for _ in range(N)]
        self.source = source
        self.sink = sink

    def add_edge(self, fr, to, cap):
        n1 = len(self.G[fr])
        n2 = len(self.G[to])
        self.G[fr].append([to, cap, n2])
        self.G[to].append([fr, 0, n1]) # 逆辺を cap 0 で追加
        
    def add_edge_undirected(self, fr, to, cap):
        n1 = len(self.G[fr])
        n2 = len(self.G[to])
        self.G[fr].append([to, cap, n2])
        self.G[to].append([fr, cap, n1]) # 逆辺を cap 0 で追加
        
    def bfs(self):
        level = [0] * self.N
        G = self.G; source = self.source; sink = self.sink
        q = deque([source])
        level[source] = 1
        pop = q.popleft; append = q.append
        while q:
            v = pop()
            lv = level[v] + 1
            for to, cap, rev in G[v]:
                if not cap:
                    continue
                if level[to]:
                    continue
                level[to] = lv
                if to == sink:
                    self.level = level
                    return
                append(to)
        self.level = level
        
    def dfs(self,v,f):
        if v == self.sink:
            return f
        G = self.G
        prog = self.progress
        level = self.level
        lv = level[v]
        E = G[v]
        for i in range(prog[v],len(E)):
            to, cap, rev = E[i]
            prog[v] = i
            if not cap:
                continue
            if level[to] <= lv:
                continue
            x = f if f < cap else cap
            ff = self.dfs(to, x)
            if ff:
                E[i][1] -= ff
                G[to][rev][1] += ff
                return ff
        return 0
    
    def max_flow(self):
        INF = 10**18
        flow = 0
        while True:
            self.bfs()
            if not self.level[self.sink]:
                return flow
            self.progress = [0] * self.N
            while True:
                f = self.dfs(self.source, INF)
                if not f:
                    break
                flow += f
        return flow

source = 0
sink = H+W+1

dinic = Dinic(H+W+2, source, sink)
add = dinic.add_edge_undirected

INF = 10 ** 18
for h in range(1,H+1):
    for w,ox in enumerate(A[h-1],1):
        if ox == 'x':
            continue
        elif ox == 'o':
            add(h,H+w,1)
        elif ox == 'S':
            add(source,h,INF)
            add(source,H+w,INF)
        elif ox == 'T':
            add(sink,h,INF)
            add(sink,H+w,INF)

f = dinic.max_flow()
answer = f if f < INF else -1
print(answer)

Submission status: Accepted

Solution code:
import sys
read = sys.stdin.buffer.read
readline = sys.stdin.buffer.readline
readlines = sys.stdin.buffer.readlines

from collections import deque

H,W = map(int,readline().split())
A = [line.rstrip().decode('utf-8') for line in readlines()]

class Dinic:
    def __init__(self, N, source, sink):
        self.N = N
        self.G = [[] for _ in range(N)]
        self.source = source
        self.sink = sink

    def add_edge(self, fr, to, cap):
        n1 = len(self.G[fr])
        n2 = len(self.G[to])
        self.G[fr].append([to, cap, n2])
        self.G[to].append([fr, 0, n1]) # 逆辺を cap 0 で追加
        
    def bfs(self):
        level = [0] * self.N
        G = self.G; source = self.source; sink = self.sink
        q = deque([source])
        level[source] = 1
        pop = q.popleft; append = q.append
        while q:
            v = pop()
            lv = level[v] + 1
            for to, cap, rev in G[v]:
                if not cap:
                    continue
                if level[to]:
                    continue
                level[to] = lv
                if to == sink:
                    self.level = level
                    return
                append(to)
        self.level = level
        
    def dfs(self,v,f):
        if v == self.sink:
            return f
        G = self.G
        prog = self.progress
        level = self.level
        lv = level[v]
        E = G[v]
        for i in range(prog[v],len(E)):
            to, cap, rev = E[i]
            prog[v] = i
            if not cap:
                continue
            if level[to] <= lv:
                continue
            x = f if f < cap else cap
            ff = self.dfs(to, x)
            if ff:
                E[i][1] -= ff
                G[to][rev][1] += ff
                return ff
        return 0
    
    def max_flow(self):
        INF = 10**18
        flow = 0
        while True:
            self.bfs()
            if not self.level[self.sink]:
                return flow
            self.progress = [0] * self.N
            while True:
                f = self.dfs(self.source, INF)
                if not f:
                    break
                flow += f
        return flow

source = 0
sink = H+W+1

dinic = Dinic(H+W+2, source, sink)
add = dinic.add_edge

INF = 10 ** 18
for h in range(1,H+1):
    for w,ox in enumerate(A[h-1],1):
        if ox == 'x':
            continue
        elif ox == 'o':
            add(h,H+w,1)
            add(H+w,h,1)
        elif ox == 'S':
            add(source,h,INF)
            add(h,source,INF)
            add(source,H+w,INF)
            add(H+w,source,INF)
        elif ox == 'T':
            add(sink,h,INF)
            add(h,sink,INF)
            add(sink,H+w,INF)
            add(H+w,sink,INF)

f = dinic.max_flow()
answer = f if f < INF else -1
print(answer)

Submission status: Accepted

Solution code:
import sys
read = sys.stdin.buffer.read
readline = sys.stdin.buffer.readline
readlines = sys.stdin.buffer.readlines

from collections import defaultdict

H,W = map(int,readline().split())
A = [line.rstrip().decode('utf-8') for line in readlines()]

source = 0
sink = H+W+1

graph = [defaultdict(int) for _ in range(H+W+2)]

INF = 10 ** 18
for h in range(1,H+1):
    for w,ox in enumerate(A[h-1],1):
        if ox == 'x':
            continue
        elif ox == 'o':
            graph[h][H+w] = 1
            graph[H+w][h] = 1
        elif ox == 'S':
            graph[source][h] = INF
            graph[h][source] = INF
            graph[source][H+w] = INF
            graph[H+w][source] = INF
        elif ox == 'T':
            graph[sink][h] = INF
            graph[h][sink] = INF
            graph[sink][H+w] = INF
            graph[H+w][sink] = INF


class Dinic():
    def __init__(self,graph,V,source,sink):
        self.graph = graph
        self.sink = sink
        self.source = source
        self.V = V
#        self.compress()
        self.N = len(V)
    
    def compress(self):
        self.N = len(self.V)
        v_to_i = {x:i for i,x in enumerate(self.V)}
        self.sink = v_to_i[self.sink]
        self.source = v_to_i[self.source]
        g = [dict() for _ in range(self.N)]
        for v,e in self.graph.items():
            vn = v_to_i[v]
            g[vn] = {v_to_i[w]:c for w,c in e.items()}
        self.graph = g
        
    def bfs(self):
        level = [0]*self.N
        q = [self.source]
        level[self.source] = 1
        d = 1
        while q:
            if level[self.sink]:
                break
            qq = []
            d += 1
            for v in q:
                for w,cap in self.graph[v].items():
                    if cap == 0:
                        continue
                    if level[w]:
                        continue
                    level[w] = d
                    qq.append(w)
            q = qq
        self.level = level
        
    def dfs(self,v,f):
        if v == self.sink:
            return f
        for w,cap in self.itr[v]:
            if cap == 0 or self.level[w] != self.level[v] + 1:
                continue
            d = self.dfs(w,min(f,cap))
            if d:
                self.graph[v][w] -= d
                self.graph[w][v] += d
                return d
        return 0
    
    def max_flow(self):
        INF = 10**18
        flow = 0
        while True:
            self.bfs()
            if self.level[self.sink] == 0:
                break
            self.itr = [iter(e.items()) for e in self.graph]
            while True:
                f = self.dfs(self.source,INF)
                if f == 0:
                    break
                flow += f
        return flow

answer = Dinic(graph=graph,V=list(range(H+W+2)),source=0,sink=H+W+1).max_flow()
if answer >= INF:
    answer = -1
print(answer)

Submission status: Accepted

Solution code:
from collections import *
import sys

sys.setrecursionlimit(10 ** 6)
int1 = lambda x: int(x) - 1
p2D = lambda x: print(*x, sep="\n")
def MI(): return map(int, sys.stdin.readline().split())
def LI(): return list(map(int, sys.stdin.readline().split()))
def LLI(rows_number): return [LI() for _ in range(rows_number)]

class Dinic():
    def __init__(self, n, s, t):
        self.n, self.s, self.t = n, s, t
        self.to = defaultdict(list)
        self.level = [-1]
        self.max_flow = -1

    def add_edge(self, u, v, cap):
        u_index_in_to_v = len(self.to[v])
        v_index_in_to_u = len(self.to[u])
        self.to[u].append([v, cap, u_index_in_to_v])
        self.to[v].append([u, 0, v_index_in_to_u])

    # 無向辺の追加
    def add_undir_edge(self, u, v, cap):
        u_index_in_to_v = len(self.to[v])
        v_index_in_to_u = len(self.to[u])
        self.to[u].append([v, cap, u_index_in_to_v])
        self.to[v].append([u, cap, v_index_in_to_u])

    def set_level(self):
        s = self.s
        level = [-1] * self.n
        level[s] = 0
        q = deque()
        q.append([s, 0])
        while q:
            u, u_level = q.popleft()
            for v, cap, _ in self.to[u]:
                if cap == 0: continue
                if level[v] != -1: continue
                level[v] = u_level + 1
                if v == self.t:
                    self.level = level
                    return True
                q.append([v, u_level + 1])
        return False

    def dfs(self, u=-1, flow_to_me=10 ** 16):
        if u == -1: u = self.s
        if u == self.t: return flow_to_me
        flow_from_me = 0
        u_level = self.level[u]
        for utov_i, (v, cap, vtou_i) in enumerate(self.to[u]):
            if self.level[v] != u_level + 1: continue
            if cap == 0: continue
            flow_to_v = self.dfs(v, min(cap, flow_to_me - flow_from_me))
            if not flow_to_v: continue
            flow_from_me += flow_to_v
            self.to[u][utov_i][1] -= flow_to_v
            self.to[v][vtou_i][1] += flow_to_v
        return flow_from_me

    def calculation(self):
        res = 0
        while self.set_level():
            res += self.dfs()
        return res

    # これが出力用
    def get_max_flow(self):
        if self.max_flow == -1:
            self.max_flow = self.calculation()
        return self.max_flow

h,w=MI()
aa=[input() for _ in range(h)]

def main():
    inf=10**9+7
    s=h+w
    t=h+w+1
    mc=Dinic(h+w+2,s,t)
    si,sj,ti,tj=-1,-2,-3,-4
    for i,row in enumerate(aa):
        for j,a in enumerate(row):
            if a=="S":
                if i==ti or j==tj:
                    print(-1)
                    exit()
                si,sj=i,j
                mc.add_edge(s,i,inf)
                mc.add_edge(s,j+h,inf)
            elif a=="T":
                if i==si or j==sj:
                    print(-1)
                    exit()
                ti,tj=i,j
                mc.add_edge(i,t,inf)
                mc.add_edge(j+h,t,inf)
            elif a=="o":
                mc.add_undir_edge(i,j+h,1)
    print(mc.get_max_flow())

main()

Submission status: Accepted

Solution code:
import sys
sys.setrecursionlimit(1000000)
def FF(E, s, t):
    NN = H+W+2
    G = [[] for _ in range(NN)]
    for a, b, f in E:
        G[a].append([b, f, len(G[b])])
        G[b].append([a, 0, len(G[a])-1])
    
    def dfs(s, t, f):
        if s == t:
            return f
        used[s] = 1
        for i, (b, _f, r) in enumerate(G[s]):
            if used[b] or _f == 0: continue
            d = dfs(b, t, min(f, _f))
            if d > 0:
                G[s][i][1] -= d
                G[b][r][1] += d
                return d
        return 0
    
    flow = 0
    while 1:
        used = [0] * NN
        f = dfs(s, t, 10**100)
        if f == 0:
            return flow
        flow += f

E = []

H, W = map(int, input().split())
for i in range(H):
    A = input()
    for j in range(W):
        if A[j] == "o":
            E.append((i, j+H, 1))
            E.append((j+H, i, 1))
        elif A[j] == "S":
            S = (i, j+H)
        elif A[j] == "T":
            T = (i, j+H)
E.append((H+W, S[0], 10**6))
E.append((H+W, S[1], 10**6))
E.append((T[0], H+W+1, 10**6))
E.append((T[1], H+W+1, 10**6))

ff = FF(E, H+W, H+W+1)
print(ff if ff < 10**6 else -1)

Submission status: Accepted

Solution code:
import sys
input = sys.stdin.readline

from scipy.sparse.csgraph import dijkstra

H,W = map(int,input().split())

# start = 0
# rows = 1,2,...,H
# cols = H+1,...,H+W
# goal = H+W+1

INF = 10 ** 9
start = 0
goal = H+W+1
V = H+W+2
graph = [[0] * V for _ in range(V)]
edges = [] # 隣接リスト
for i in range(H):
    row = input()
    for j,cell in enumerate(row):
        if cell == 'o':
            graph[1+i][1+H+j] = 1
            graph[1+H+j][1+i] = 1
    s = row.find('S')
    t = row.find('T')
    if s != -1:
        graph[start][1+i] = INF
        graph[start][1+H+s] = INF
    if t != -1:
        graph[1+i][goal] = INF
        graph[1+H+t][goal] = INF

# あとは max flow を求めればよい

def max_flow(graph):
    f = 0
    while True:
        if f > 200:
            return -1
        dist,pred = dijkstra(graph, indices = start, unweighted = True, return_predecessors = True)
        if dist[goal] > INF:
            return f
        f += 1
        after = goal
        while after != start:
            before = pred[after]
            graph[before][after] -= 1
            graph[after][before] += 1
            after = before

answer = max_flow(graph)
print(answer)