码迷,mamicode.com
首页 > 其他好文 > 详细

AtCoder - 2568 最小割

时间:2019-01-25 15:09:20      阅读:252      评论:0      收藏:0      [点我收藏+]

标签:objective   exactly   object   int   else   new   nec   i++   inpu   

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
  • 2H,W100
  • 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 最小割

标签:objective   exactly   object   int   else   new   nec   i++   inpu   

原文地址:https://www.cnblogs.com/zxyqzy/p/10319374.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!