当前位置: 首页 > news >正文

【题解】P2472 [SCOI2007] 蜥蜴 [网络流]

P2472 [SCOI2007] 蜥蜴 - 洛谷 (luogu.com.cn) (水紫)

一看到网格就想用 bfs,看到数据范围老实了。

本质上是资源分配,从一个状态达到另一个状态有代价并且限量,还要最大化结束状态的数量。

这不网络流吗?


(我真没听过 “平面距离” 这个叫法,不如直接说欧几里得距离或者曼哈顿距离,d 就是欧氏距离)

想好算法后这题就很简单了,考虑到没有源汇点,我们自己增加 S 为源点,T 为汇点。

首先,S 连大小为 1 的边到一开始有蜥蜴的格子(因为每个格子上只能有 1 只蜥蜴),

能直接到边界外面的格子连无限大的边到 T

然后很重要的一点:本题是节点限制流量,不是边限制流量

这代表着我们要将每个点拆成入点和出点,入点 -> 出点的边流量就是每个点的石像高度 h

这代表能通过这个点走向别的格子的蜥蜴只能有 h 只,真正实现了单点边权做不到的点流限制

从其他点出点连到入点的边,容量为无限大,

这代表所有蜥蜴都可以走进来(但不一定走的出去)。

总结流程:

(0)给格子(入点出点)编号,方便管理。

(1)源点 S 连到有蜥蜴的格子入点,边权为 1。

(2)格子自己入点连到自己出点,边权为 h[x][y]。

(3)格子的出点连到能到达(欧氏距离小于等于 d)的格子入点,边权为 inf。

(4)能到达边界外面的格子出点连到汇点 T,边权为 inf。

代码(我去我 dinic 模板打错了调了俩小时再也不敢不背模板了):

#include<bits/stdc++.h>
using namespace std;typedef pair<int, int> PII;
const int N = 23;
const int M = 2 * N * N;   // 网络流点数 
const int E = M * M * 2;   // 边数 
const int INF = 1e9;int n, m, D;
int h[N][N]; char s[N][N];
int S, T;
map<PII, int> mp;   // 编号 struct edge {int x, y, f, pre;
} e[E];
int elen, last[M], cur[M];void ins(int x, int y, int f) {   // 我流链式前向星 elen ++; e[elen] = {x, y, f, last[x]}; last[x] = elen;elen ++; e[elen] = {y, x, 0, last[y]}; last[y] = elen;
}bool jd_bon(int x, int y) {return min(min(n - x + 1, m - y + 1), min(x, y)) <= D;   // 到上下左右边界外最小的距离小于等于 D 
}int get_dis(int a, int b, int c, int d) {return (a - c) * (a - c) + (b - d) * (b - d);   // 整数计算避免精度 
}void jd_find(int x, int y) {for (int i = 1; i <= n; i ++) {for (int j = 1; j <= m; j ++) {int t = get_dis(x, y, i, j);if (t <= D * D && t != 0) {    // 在范围之内 int tx = mp[{x, y}], ty = mp[{i, j}];ins(tx ^ 1, ty, INF);     //出点 -> (欧氏距离小于等于 d)入点}}}
}bool v[M]; int d[M];bool spfa() {memset(v, 0, sizeof(v)); v[S] = 1;queue<int> Q; Q.push(S); memset(d, 0x7f, sizeof(d));int inf = d[1]; d[S] = 0;while (!Q.empty()) {int x = Q.front(); Q.pop(); v[x] = 0;for (int k = last[x]; k; k = e[k].pre) if (e[k].f) {  // 有流量 int y = e[k].y;if (d[y] > d[x] + 1) {d[y] = d[x] + 1;if (!v[y]) {Q.push(y);v[y] = 1;}}}} return (d[T] != inf);
}int dinic(int x, int f) {int sx = 0; v[x] = 1;if (x == T || (!f)) {return f;}for (int k = cur[x]; k; k = e[k].pre) if (e[k].f) {  // 弧优化 int y = e[k].y; cur[x] = k;if (d[y] == d[x] + 1 && !v[y]) {   // y 是 x 下一层的,并且还能得到流量 int sy = dinic(y, min(e[k].f, f - sx));sx += sy; e[k].f -= sy; e[k ^ 1].f += sy;if (sx == f) {return f;}}}if (sx) {v[x] = 0;}return sx;
}int main () {ios::sync_with_stdio(false);cin.tie(0);cin >> n >> m >> D;S = 0; T = 1;int len = 1;   // 格子编号从 2 开始 memset (last, 0, sizeof(last));elen = 1;     // 双向边 elen = 1 for (int i = 1; i <= n; i ++) {cin >> (s[i] + 1);for (int j = 1; j <= m; j ++) {h[i][j] = s[i][j] - '0';len ++;mp[{i, j}] = len;   // 偶数入点,奇数出点 len ++;}}int sum = 0;   // 蜥蜴个数 for (int i = 1; i <= n; i ++) {cin >> (s[i] + 1);for (int j = 1; j <= m; j ++) if (s[i][j] == 'L') {sum ++;int t = mp[{i, j}];ins(S, t, 1);    // 源点 -> 蜥蜴格子入点 }} for (int i = 1; i <= n; i ++) {for (int j = 1; j <= m; j ++) {int t = mp[{i, j}];ins(t, t ^ 1, h[i][j]);   // 格子自身入点 -> 出点 if (jd_bon(i, j) && h[i][j]) {ins(t ^ 1, T, INF);   // 能到边界的格子 -> 汇点 }}}for (int i = 1; i <= n; i ++) {for (int j = 1; j <= m; j ++) {jd_find(i, j);         // 两个格子之间连边 }}int ans = 0;memset(v, 0, sizeof(v));while (spfa()) {memcpy(cur, last, sizeof(last));ans += dinic(S, INF);} cout << sum - ans << "\n";   // 总数 - 逃出去的 return 0;
} 

http://www.dtcms.com/a/592658.html

相关文章:

  • RV1126 NO.47:RV1126+OPENCV对视频流进行视频腐蚀操作
  • 消息称苹果 iPhone 17 系列国内激活销量超 825 万
  • 狠狠做网站 百度一下做家政服务网站
  • 企业网站 php定制软件开发公司
  • SAP-ABAP:SAP 系统与外部服务的 HTTP 通信cl_http_client 的深度解析与应用实践
  • COC Asia 2025|得帆云 ETL:顺应 Hive 新特性,重塑数据管道的未来
  • 深度学习:基于YOLOv8模型的海洋生物目标检测系统 深度学习 pytorch 计算机 PySide6界面✅
  • 学习随笔-http和https有何区别
  • 八、深度学习中的正则化
  • Vue中使用axios+pinia实现token续期功能,自动刷新token
  • Pano2vr6制作全景html5
  • 100% 本地 MCP 客户端 + SQLite 服务器(LlamaIndex + Ollama + Qwen2.5)
  • 博客网站素材免费静态网站模板下载
  • 做营销网站建设北仑网站建设案例
  • HarmonyOS:相对布局(RelativeContainer)
  • 【数据库】国产数据库替代实战:金仓KES如何以“智能运维 + 低资源占用”年省百万运维成本?
  • pandas__unstack方法与set_index详解
  • JS 前端存储实战指南:从基础缓存到离线数据库,构建可靠的数据持久化体系
  • Python应用开发学习:Pygame中实现切换开关及鼠标拖动连续填充功能
  • 2025年--Lc231-350. 两个数组的交集 II-Java版
  • 调试原理[简要描述]
  • NVLink技术
  • 栖霞建设网站响应式网站建设免费
  • 零样本数据集(不需要样本级文本)
  • 虾分发用户体验优化:让内测更懂用户需求
  • Jenkins和Arbess,开源免费CI/CD工具选型指南
  • HTTP/2在EDI领域中的优势:构建高效、安全、现代化的数据交换基石
  • 地图可视化实践录:TopoJSON学习
  • 微算法科技(NASDAQ MLGO)将租赁权益证明(LPoS)共识算法与零知识证明结合,实现租赁代币的隐私保护
  • 徕卡RTC360三维激光扫描仪摔坏故障维修方案