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 (ij).

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 (ij) is given to you by a character aij, 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
  • aij is ., o, S or T.
  • There is exactly one S among aij.
  • There is exactly one T among aij.

Input

Input is given from Standard Input in the following format:

H W
a11 a1W
:
aH1 aHW

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

有意思的网络流题目;
刚开始我想的很直接:按题目建边,但是你会发现这样建边之后复杂度会很高,而且也不现实;
我们考虑将行和列分开;
对于源点,我们将其和该行建边,与该列建边;
同理对于汇点;
对于O这种情况,我们将行和列建边,容量为1;
由于我们要使得S,T分开,所以要求的是最小割,那么就是dinic求一下最大流即可;
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstdlib>
#include<cstring>
#include<string>
#include<cmath>
#include<map>
#include<set>
#include<vector>
#include<queue>
#include<bitset>
#include<ctime>
#include<deque>
#include<stack>
#include<functional>
#include<sstream>
//#include<cctype>
//#pragma GCC optimize(2)
using namespace std;
#define maxn 2000005
#define inf 0x7fffffff
//#define INF 1e18
#define rdint(x) scanf("%d",&x)
#define rdllt(x) scanf("%lld",&x)
#define rdult(x) scanf("%lu",&x)
#define rdlf(x) scanf("%lf",&x)
#define rdstr(x) scanf("%s",x)
typedef long long ll;
typedef unsigned long long ull;
typedef unsigned int U;
#define ms(x) memset((x),0,sizeof(x))
const long long int mod = 1e9 + 7;
#define Mod 1000000000
#define sq(x) (x)*(x)
#define eps 1e-4
typedef pair<int, int> pii;
#define pi acos(-1.0)
//const int N = 1005;
#define REP(i,n) for(int i=0;i<(n);i++)
typedef pair<int, int> pii;
inline ll rd() {
ll x = 0;
char c = getchar();
bool f = false;
while (!isdigit(c)) {
if (c == '-') f = true;
c = getchar();
}
while (isdigit(c)) {
x = (x << 1) + (x << 3) + (c ^ 48);
c = getchar();
}
return f ? -x : x;
} ll gcd(ll a, ll b) {
return b == 0 ? a : gcd(b, a%b);
}
int sqr(int x) { return x * x; } /*ll ans;
ll exgcd(ll a, ll b, ll &x, ll &y) {
if (!b) {
x = 1; y = 0; return a;
}
ans = exgcd(b, a%b, x, y);
ll t = x; x = y; y = t - a / b * y;
return ans;
}
*/ int n, m;
int st, ed;
struct node {
int u, v, nxt, w;
}edge[maxn << 1]; int head[maxn], cnt; void addedge(int u, int v, int w) {
edge[cnt].u = u; edge[cnt].v = v; edge[cnt].nxt = head[u];
edge[cnt].w = w; head[u] = cnt++;
} int rk[maxn]; int bfs() {
queue<int>q;
ms(rk);
rk[st] = 1;
q.push(st);
while (!q.empty()) {
int tmp = q.front(); q.pop();
for (int i = head[tmp]; i != -1; i = edge[i].nxt) {
int to = edge[i].v;
if (rk[to] || edge[i].w <= 0)continue;
rk[to] = rk[tmp] + 1; q.push(to);
}
}
return rk[ed];
} int dfs(int u, int flow) {
if (u == ed)return flow;
int add = 0;
for (int i = head[u]; i != -1 && add < flow; i = edge[i].nxt) {
int v = edge[i].v;
if (rk[v] != rk[u] + 1 || !edge[i].w)continue;
int tmpadd = dfs(v, min(edge[i].w, flow - add));
if (!tmpadd) { rk[v] = -1; continue; }
edge[i].w -= tmpadd; edge[i ^ 1].w += tmpadd;
add += tmpadd;
}
return add;
} int ans;
void dinic() {
while (bfs())ans += dfs(st, inf);
}
int H, W;
char ch[103][103]; int getpos(int x, int y) {
return (x - 1)*W + y;
}
int main() {
// ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
cin >> H >> W; memset(head, -1, sizeof(head));
for (int i = 1; i <= H; i++)scanf("%s", ch[i] + 1);
int hx = 0, hy = 0, wx = 0, wy = 0;
for (int i = 1; i <= H; i++) {
for (int j = 1; j <= W; j++) {
if (ch[i][j] == 'S') {
hx = i; hy = j;
}
else if (ch[i][j] == 'T') {
wx = i; wy = j;
}
}
}
if (wx == hx || wy == hy) {
cout << -1 << endl; return 0;
}
st = 0; ed = H * W + 1;
for (int i = 1; i <= H; i++) {
for (int j = 1; j <= W; j++) {
if (ch[i][j] == 'S')addedge(st, i, inf), addedge(i, st, 0), addedge(st, j + H, inf), addedge(j + H, st, 0);
if (ch[i][j] == 'T')addedge(i, ed, inf), addedge(ed, i, 0), addedge(j + H, ed, inf), addedge(ed, j + H, 0);
if (ch[i][j] != '.')addedge(i, j + H, 1), addedge(j + H, i, 0), addedge(j + H, i, 1), addedge(i, j + H, 0); }
}
dinic();
if (ans != inf) {
cout << ans << endl; return 0;
}
else cout << -1 << endl;
return 0;
}

AtCoder - 2568 最小割的更多相关文章

  1. Atcoder Grand Contest 038 F - Two Permutations(集合划分模型+最小割)

    洛谷题面传送门 & Atcoder 题面传送门 好久前做的题了--今天偶然想起来要补个题解 首先考虑排列 \(A_i\) 要么等于 \(i\),要么等于 \(P_i\) 这个条件有什么用.我们 ...

  2. Atcoder Regular Contest 125 E - Snack(最小割转化+贪心)

    Preface: 这是生平第一道现场 AC 的 arc E,也生平第一次经历了 performance \(\ge 2800\)​,甚至还生平第一次被 hb 拉到会议里讲题,讲的就是这个题,然鹅比较尬 ...

  3. [题解] Atcoder ARC 142 E Pairing Wizards 最小割

    题目 建图很妙,不会. 考虑每一对要求合法的巫师(x,y),他们两个的\(a\)必须都大于\(min(b_x,b_y)\).所以在输入的时候,如果\(a_x\)或者\(a_y\)小于\(min(b_x ...

  4. BZOJ 1391: [Ceoi2008]order [最小割]

    1391: [Ceoi2008]order Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 1509  Solved: 460[Submit][Statu ...

  5. BZOJ-2127-happiness(最小割)

    2127: happiness(题解) Time Limit: 51 Sec  Memory Limit: 259 MBSubmit: 1806  Solved: 875 Description 高一 ...

  6. BZOJ-2561-最小生成树 题解(最小割)

    2561: 最小生成树(题解) Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1628  Solved: 786 传送门:http://www.lyd ...

  7. BZOJ3438 小M的作物(最小割)

    题目 Source http://www.lydsy.com/JudgeOnline/problem.php?id=3438 Description 小M在MC里开辟了两块巨大的耕地A和B(你可以认为 ...

  8. 最大流-最小割 MAXFLOW-MINCUT ISAP

    简单的叙述就不必了. 对于一个图,我们要找最大流,对于基于增广路径的算法,首先必须要建立反向边. 反向边的正确性: 我努力查找了许多资料,都没有找到理论上关于反向边正确性的证明. 但事实上,我们不难理 ...

  9. bzoj1412最小割

    太羞耻了,m n写反了(主要是样例n m相等) 建图方法比较高(ji)端(chu),对于可以加栅栏的地方连上1的边,然后求最小割即可 为了让代码优(suo)美(duan),我写了一个check,避免多 ...

随机推荐

  1. ansible基本使用

    ansible介绍 基础概念 ansible是个配置管理工具,可以批量处理一些任务.ansible只需要依赖ssh即可使用,而不需要在受管主机上安装客户端工具. ansible具有幂等性,即以结果为导 ...

  2. swift之xib关联UIView

    有点坑爹,设置file owner 不行,搞了一早上,来说下怎么关联吧 自定义UIView要重写 required init(coder aDecoder: NSCoder) { super.init ...

  3. Python模块及其导入

    一.模块 1.模块的定义: 为了编写可维护的代码,我们把很多函数分组,分别放到不同的文件里,这样,每个文件包含的代码就相对较少, 很多编程语言都采用这种组织代码的方式.在Python中,一个.py文件 ...

  4. copyWithZone详解

    [copyWithZone详解] NSObject实现了-copy.+copy.+copyWithZone方法.代码如下: + (id)copy { return (id)self; } + (id) ...

  5. SpringDataRedis操作Redis简单案例

    Jedis Jedis是Redis官方推出的一款面向Java的客户端,提供了很多接口供Java语言调用.可以在Redis官网下载,当然还有一些开源爱好者提供的客户端,如Jredis.SRP等等,推荐使 ...

  6. Leetcode:Substring with Concatenation of All Words分析和实现

    题目大意是传入一个字符串s和一个字符串数组words,其中words中的所有字符串均等长.要在s中找所有的索引index,使得以s[index]为起始字符的长为words中字符串总长的s的子串是由wo ...

  7. 【HDU4960】Another OCD Patient

    题意 给出一个长度为n的整数序列.可以将一段连续的序列进行合并.合并的长度不同代价不同.问付出最少多少代价可以将这个序列变成一个对称的序列.n<=5000 分析 一看题感觉是个dp很好写啊.f[ ...

  8. GNU 和 g++(转)

    百度知道 GNU计划,又称革奴计划,是由Richard Stallman在1983年9月27日公开发起的.它的目标是创建一套完全自由的操作系统.Richard Stallman最早是在net.unix ...

  9. ZIP压缩格式与RAR压缩格式

    早已习惯了安装系统之后必须安装winrar,压缩文件也已经习惯了rar格式,这种习惯的力量真的挺可怕的.在工作中你的同事可能没有安装winrar,或者他们不喜欢安装盗版软件,这时候你给他们发送过去的是 ...

  10. [docker]本地仓库的创建的使用

    如果自己创建的镜像可以供其他同事使用,那就可以大大节约开发时间成本,docker的本地仓库正好可以满足这样的需求 1.在仓库服务器上创建本地仓库 baylor@baylor-virtual-machi ...