P2472 [SCOI2007] 蜥蜴 【最大流】

对点有限制,考察拆点的技巧

当时犯了一个傻逼错误:

 

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e6+15;
const int INF = 1e9;
const int mo = 998244353;
#define pb push_back
#define pii pair<int,int>
#define ft first
#define sd second
#define ffor(i,a,b,c) for(int i=(a);i<(b);i+=(c))
#define For(i,a,b,c) for(int i=(a);i<=(b);i+=(c))
#define rfor(i,a,b,c) for(int i=(a);i>(b);i-=(c))
#define Rfor(i,a,b,c) for(int i=(a);i>=(b);i-=(c))
#define all(x) (x).begin(), (x).end()
#define debug1(x) cerr<<"! "<<x<<endl;
#define debug2(x,y) cerr<<"#  "<<x<<" "<<y<<endl;
int head[N], cnt;
int S, T;
struct edge
{
	int to, nxt, w;
}e[N << 1];
void add(int u, int v, int w) {
	e[cnt].to = v;
	e[cnt].w = w;
	e[cnt].nxt = head[u];
	head[u] = cnt++;
}
int dep[N], cur[N];
bool bfs() {
	memset(dep, -1, sizeof(dep));
	queue<int> q;
	q.push(S); dep[S] = 0;
	cur[S] = head[S];
	while (!q.empty()) {
		int u = q.front(); q.pop();
		for (int i = head[u]; ~i; i = e[i].nxt) {
			int v = e[i].to;
			if (dep[v] == -1 && e[i].w) {
				dep[v] = dep[u] + 1;
				cur[v] = head[v];
				if (v == T) return true;
				q.push(v);
			}
		}
	}
	return false;
}
int dfs(int u, int limit) {
	if (u == T) return limit;
	int flow = 0;
	for (int i = cur[u]; ~i && flow < limit; i = e[i].nxt) {
		cur[u] = i;
		int v = e[i].to;
		if (dep[v] == dep[u] + 1 && e[i].w) {
			int mif = dfs(v, min(e[i].w, limit - flow));
			e[i].w -= mif;
			e[i ^ 1].w += mif;
			flow += mif;
			if (flow == limit) return flow;
		}
	}
	return flow;
}
int dinic() {
	int res = 0;
	while (bfs()) {
		res += dfs(S, INF);
	}
	return res;
}
void slv(){
	memset(head, -1, sizeof(head));
	int r, c, d; cin >> r >> c >> d;
	vector<vector<int>> mp(r + 1, vector<int>(c + 1));
	map<pii, pii> zb; int tot = 0; S = 0, T = 2 * r * c + 1; 
	auto cal = [&] (int x, int y) {
		for (int i = x - d; i <= x + d; i++) {
			for (int j = y - d; j <= y + d; j++) {
				if (i == x && j == y) continue;
				if (mp[x][y] == 0) continue;
				if ((x - i) * (x - i) + (y - j) * (y - j) > d * d) continue;
				int ru = zb[{x, y}].ft, ou = zb[{x, y}].sd;				
				if (i < 1 || j < 1) {										
					add(ou, T, INF);
					add(T, ou, 0);
					return;
				}
				if (i > r || j > c) {
					add(ou, T, INF);
					add(T, ou, 0);
					return;
				}
				if (mp[i][j]) {
					int ru1 = zb[{i, j}].ft, ou1 = zb[{i, j}].sd;		
					assert(ru1 && ou1);		
					add(ou, ru1, INF);
					add(ru1, ou, 0);
					// cout << x << ' ' << y << ' ' << i << ' ' << j << '\n';
				}
			}
		}
	};
	for (int i = 1; i <= r; i++) {
		for (int j = 1; j <= c; j++) {
			char tmp; cin >> tmp;
			mp[i][j] = tmp - '0';
			if (mp[i][j]) {
				if (zb[{i, j}].ft == 0) {
					int ru = ++tot;
					int ou = ++tot;
					zb[{i, j}] = {ru, ou};
				}
				int ru = zb[{i, j}].ft, ou = zb[{i, j}].sd;
				add(ru, ou, mp[i][j]);
				add(ou, ru, 0);
			}
		}
	} 
	for (int i = 1; i <= r; i++) {
		for (int j = 1; j <= c; j++) {
			cal(i, j);
		}
	}
	vector<vector<char>> mp2(r + 1, vector<char>(c + 1));
	int ans = 0;
	for (int i = 1; i <= r; i++) {
		for (int j = 1; j <= c; j++) {
			cin >> mp2[i][j];
			if (mp2[i][j] == 'L') {
				ans++;
				if (zb[{i, j}].ft == 0) {
					int ru = ++tot;
					int ou = ++tot;
					zb[{i, j}] = {ru, ou};
				}
				int ru = zb[{i, j}].ft;
				add(S, ru, 1);
				add(ru, S, 0);
			} 
		}
	}
	// debug1(tot)
	// cout << zb[{3, 3}].ft << " " << zb[{3, 3}].sd << endl;
	cout << ans - dinic() << '\n';
}
int main(){
	ios::sync_with_stdio(false);cin.tie(0);
	slv();
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值