天天看點

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;
}