#Codeforces Round #583 D. Treasure Island (BFS 或 最小割)

14 篇文章 0 订阅
7 篇文章 0 订阅

 

  • D. Treasure Island

    time limit per test

    1 second

    memory limit per test

    512 megabytes

    input

    standard input

    output

    standard output

    All of us love treasures, right? That's why young Vasya is heading for a Treasure Island.

    Treasure Island may be represented as a rectangular table n×mn×m which is surrounded by the ocean. Let us number rows of the field with consecutive integers from 11 to nn from top to bottom and columns with consecutive integers from 11 to mm from left to right. Denote the cell in rr-th row and cc-th column as (r,c)(r,c). Some of the island cells contain impassable forests, and some cells are free and passable. Treasure is hidden in cell (n,m)(n,m).

    Vasya got off the ship in cell (1,1)(1,1). Now he wants to reach the treasure. He is hurrying up, so he can move only from cell to the cell in next row (downwards) or next column (rightwards), i.e. from cell (x,y)(x,y) he can move only to cells (x+1,y)(x+1,y) and (x,y+1)(x,y+1). Of course Vasya can't move through cells with impassable forests.

    Evil Witch is aware of Vasya's journey and she is going to prevent him from reaching the treasure. Before Vasya's first move she is able to grow using her evil magic impassable forests in previously free cells. Witch is able to grow a forest in any number of any free cells except cells (1,1)(1,1) where Vasya got off his ship and (n,m)(n,m) where the treasure is hidden.

    Help Evil Witch by finding out the minimum number of cells she has to turn into impassable forests so that Vasya is no longer able to reach the treasure.

    Input

    First line of input contains two positive integers nn, mm (3≤n⋅m≤10000003≤n⋅m≤1000000), sizes of the island.

    Following nn lines contains strings sisi of length mm describing the island, jj-th character of string sisi equals "#" if cell (i,j)(i,j) contains an impassable forest and "." if the cell is free and passable. Let us remind you that Vasya gets of his ship at the cell (1,1)(1,1), i.e. the first cell of the first row, and he wants to reach cell (n,m)(n,m), i.e. the last cell of the last row.

    It's guaranteed, that cells (1,1)(1,1) and (n,m)(n,m) are empty.

    Output

    Print the only integer kk, which is the minimum number of cells Evil Witch has to turn into impassable forest in order to prevent Vasya from reaching the treasure.

    Examples

    input

    Copy

    2 2
    ..
    ..

    output

    Copy

    2

    input

    Copy

    4 4
    ....
    #.#.
    ....
    .#..

    output

    Copy

    1

    input

    Copy

    3 4
    ....
    .##.
    ....

    output

    Copy

    2

    Note

    The following picture illustrates the island in the third example. Blue arrows show possible paths Vasya may use to go from (1,1)(1,1) to (n,m)(n,m). Red illustrates one possible set of cells for the Witch to turn into impassable forest to make Vasya's trip from (1,1)(1,1) to (n,m)(n,m)impossible.

 题目大意 : 输入一个N *M 由 "."和 "#"构成的矩阵, 点代表可以走, 问你最小需要更改几个"."变成"#", 使无法从(1, 1)到达(n, m)

思路 : 看完题目第一反应是最小割, 这样是可以写的,可惜比赛的时候数组开小了,一直RE16, 后来用两次BFS写过了, 因为你更改的数量只有0, 1, 2三种选择, 如果第一次就不能到达, 输出0, 如果可以,将走过的路径全部标标记不可走, 再跑一次BFS,如果这次还可以到, 输出2, 否则输出1

Accepted code

最小割版本(板子就不备注了):

#include<bits/stdc++.h>
#include<unordered_map>
using namespace std;

#define sc scanf
#define ls rt << 1
#define rs ls | 1
#define Min(x, y) x = min(x, y)
#define Max(x, y) x = max(x, y)
#define ALL(x) (x).begin(),(x).end()
#define SZ(x) ((int)(x).size())
#define MEM(x, b) memset(x, b, sizeof(x))
#define lowbit(x) ((x) & (-x))
#define P2(x) ((x) * (x))

typedef long long ll;
const int MOD = 1e9 + 7;
const int MAXN = 2e6 + 100;
const int INF = 0x3f3f3f3f;
inline ll fpow(ll a, ll b){ ll r = 1, t = a; while (b){ if (b & 1)r = (r*t) % MOD; b >>= 1; t = (t*t) % MOD; }return r; }

struct Edge
{
	int v, w, r;
};
vector <Edge> e[MAXN * 3];
int n, m, T, X;
int dep[MAXN], cur[MAXN], sp, tp;
bool vis[MAXN];
string line[MAXN];
void add(int from, int to, int w) {
	e[from].push_back({ to, w, SZ(e[to]) });
	e[to].push_back({ from, 0, SZ(e[from]) - 1 });
}
bool bfs() {
	queue <int> q; MEM(dep, 0);
	dep[sp] = 1, q.push(sp);
	while (!q.empty()) {
		int now = q.front();
		q.pop();
		for (int i = 0; i < SZ(e[now]); i++) {
			int vi = e[now][i].v, wi = e[now][i].w;
			if (!dep[vi] && wi) {
				dep[vi] = dep[now] + 1;
				q.push(vi);
			}
		}
	}
	if (dep[tp]) return true;
	else return false;
}
int dfs(int x, int dist) {
	if (x == tp || dist == 0) return dist;
	int res = 0, r;
	for (int &i = cur[x]; i < SZ(e[x]); i++) {
		int vi = e[x][i].v, wi = e[x][i].w;
		if (dep[vi] == dep[x] + 1 && wi) {
			r = dfs(vi, min(wi, dist - res));
			if (r > 0) {
				e[x][i].w -= r;
				e[vi][e[x][i].r].w += r;
				res += r;
				if (res == dist) return dist;
			}
		}
	}
	if (!res) dep[x] = 0;
	return res;
}
int dinic() {
	int flow = 0, ans;
	while (bfs()) {
		MEM(cur, 0);
		flow += dfs(sp, INF);
	}
	return flow;
}

int main()
{
	cin >> n >> m; sp = n * m + 1, tp = n * m;
	for (int i = 0; i < n; i++) cin >> line[i];
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < m; j++) {
			if (line[i][j] == '.') {
				add(i * m + j + 1, i * m + j + 1 + n * m, 1);
				if (j + 1 < m && line[i][j + 1] == '.')
					add(i * m + j + 1 + n * m, i * m + j + 2, 1);
				if (i + 1 < n && line[i + 1][j] == '.')
					add(i * m + j + 1 + n * m, (i + 1) * m + j + 1, 1);
			}
		}
	}
	int ans = dinic();
	printf("%d\n", ans);
	return 0;
}

BFS版本:

#include<bits/stdc++.h>
#include<unordered_map>
using namespace std;

#define sc scanf
#define ls rt << 1
#define rs ls | 1
#define Min(x, y) x = min(x, y)
#define Max(x, y) x = max(x, y)
#define ALL(x) (x).begin(),(x).end()
#define SZ(x) ((int)(x).size())
#define MEM(x, b) memset(x, b, sizeof(x))
#define lowbit(x) ((x) & (-x))
#define P2(x) ((x) * (x))

typedef long long ll;
const int MOD = 1e9 + 7;
const int MAXN = 1e6 + 10;
const int INF = 0x3f3f3f3f;
inline ll fpow(ll a, ll b){ ll r = 1, t = a; while (b){ if (b & 1)r = (r*t) % MOD; b >>= 1; t = (t*t) % MOD; }return r; }

struct node
{
	int x, y, pre;
};
vector <vector <int> > vis;
vector <node> e;
string mp[MAXN];
int n, m, flag;
int dir[2][2] = { 1, 0, 0, 1 };
void bfs() {
	queue <node> q; q.push({ 0, 0, -1 });
	vis[0][0] = 1;
	while (!q.empty()) {
		node now = q.front();
		q.pop();
		e.push_back(now);
		if (now.x == n - 1 && now.y == m - 1) {
			flag = 1;
			return;
		}
		for (int i = 0; i < 2; i++) {
			int xx = now.x + dir[i][0];
			int yy = now.y + dir[i][1];
			if (xx >= 0 && xx < n && yy >= 0 && yy < m && !vis[xx][yy] && mp[xx][yy] == '.') {
				vis[xx][yy] = 1;
				q.push({ xx, yy, SZ(e) - 1 });
			}
		}
	}
}

int main()
{
	cin >> n >> m;
	vis.resize(n + 5);
	for (int i = 0; i < n + 5; i++) vis[i].resize(m + 5);
	for (int i = 0; i < n; i++) cin >> mp[i];
	bfs();  // 第一次
	if (!flag) cout << 0 << endl, exit(0);  // 不可走直接输出
	flag = 0; for (int i = 0; i < n; i++) vis[i].clear();  // 清空
	vis.resize(n + 5);
	for (int i = 0; i < n + 5; i++) vis[i].resize(m + 5);
	int j = SZ(e) - 1;
	while (e[j].pre != -1) {  // 标记走过的路
		if (e[j].x == n - 1 && e[j].y == m - 1) { j = e[j].pre; continue; }
		mp[e[j].x][e[j].y] = '#';
		j = e[j].pre;
	}
	bfs();  // 再跑一次
	if (flag) cout << 2 << endl, exit(0);
	cout << 1 << endl;
	return 0;
}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值