天天看点

AtCoder - 2568 最小割

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 aij, as follows:

  • ​.​

    ​ : A square without a leaf.
  • ​o​

    ​ : A square with a leaf floating on the water.
  • ​S​

    ​ : A square with the leafS.
  • ​T​

    ​ : A square with the leafT.

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
  • aijis​

    ​.​

    ​​,​

    ​o​

    ​​,​

    ​S​

    ​​ or​

    ​T​

    ​.
  • There is exactly one​

    ​S​

    ​ amongaij.
  • There is exactly one​

    ​T​

    ​ amongaij.

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

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      
5

有意思的网络流题目;
刚开始我想的很直接:按题目建边,但是你会发现这样建边之后复杂度会很高,而且也不现实;
我们考虑将行和列分开;
对于源点,我们将其和该行建边,与该列建边;
同理对于汇点;
对于O这种情况,我们将行和列建边,容量为1;
由于我们要使得S,T分开,所以要求的是最小割,那么就是dinic求一下最大流即可;      
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
//#include
//#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 pii;
#define pi acos(-1.0)
//const int N = 1005;
#define REP(i,n) for(int i=0;i<(n);i++)
typedef pair 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() {
  queueq;
  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;
}