25 条题解
-
1
搬运工 (syrth0p1) LV 10 @ 2026-03-11 12:02:55
有点坑,ai改了几个版本再结合起来才AC。
代码仅供参考。#include <iostream> #include <vector> #include <stack> #include <set> #include <queue> #include <algorithm> using namespace std; // 上下左右四个方向 const int dx[] = {-1, 1, 0, 0}; const int dy[] = {0, 0, -1, 1}; int n, m; vector<vector<int>> grid; int bx = -1, by = -1; // 电池坐标 // ---------------------- 电源短路检测 ---------------------- // BFS检查两点在无灯泡的子图中是否连通(电池位置视为不可通过) bool bfs_check_connect(int sx, int sy, int tx, int ty) { vector<vector<bool>> visited(m, vector<bool>(n, false)); queue<pair<int, int>> q; q.push({sx, sy}); visited[sx][sy] = true; while (!q.empty()) { auto [x, y] = q.front(); q.pop(); if (x == tx && y == ty) return true; for (int d = 0; d < 4; ++d) { int nx = x + dx[d]; int ny = y + dy[d]; // 边界检查,不能是电池位置,不能是0/灯泡,未访问 if (nx < 0 || nx >= m || ny < 0 || ny >= n) continue; if (nx == bx && ny == by) continue; // 移除电池 if (grid[nx][ny] == 0 || grid[nx][ny] == 3) continue; // 障碍物/灯泡都不可通过 if (!visited[nx][ny]) { visited[nx][ny] = true; q.push({nx, ny}); } } } return false; } // 检测是否存在电源短路(电池在无灯泡的环里) bool has_power_short_circuit() { vector<pair<int, int>> neighbors; // 收集电池在无灯泡子图中的邻居 for (int d = 0; d < 4; ++d) { int nx = bx + dx[d]; int ny = by + dy[d]; if (nx >= 0 && nx < m && ny >= 0 && ny < n && grid[nx][ny] == 1) { neighbors.emplace_back(nx, ny); } } // 邻居数小于2,不可能形成环 if (neighbors.size() < 2) return false; // 检查任意两个邻居是否连通,连通则说明电池在环里 for (int i = 0; i < neighbors.size(); ++i) { for (int j = i + 1; j < neighbors.size(); ++j) { if (bfs_check_connect(neighbors[i].first, neighbors[i].second, neighbors[j].first, neighbors[j].second)) { return true; } } } return false; } // ---------------------- 点双连通分量求解(统计能亮的灯泡) ---------------------- vector<vector<int>> dfn, low; int time_stamp = 0; stack<pair<pair<int, int>, pair<int, int>>> edge_stack; vector<set<pair<int, int>>> bcc_list; void tarjan(int x, int y, int parent_x, int parent_y) { dfn[x][y] = low[x][y] = ++time_stamp; int child_cnt = 0; for (int d = 0; d < 4; ++d) { int nx = x + dx[d]; int ny = y + dy[d]; // 越界、障碍物、父节点,跳过 if (nx < 0 || nx >= m || ny < 0 || ny >= n) continue; if (grid[nx][ny] == 0) continue; if (nx == parent_x && ny == parent_y) continue; if (dfn[nx][ny] == 0) { child_cnt++; edge_stack.push({{x, y}, {nx, ny}}); tarjan(nx, ny, x, y); low[x][y] = min(low[x][y], low[nx][ny]); // 发现割点,提取点双连通分量 if ((parent_x == -1 && parent_y == -1 && child_cnt > 1) || (parent_x != -1 && low[nx][ny] >= dfn[x][y])) { set<pair<int, int>> bcc; while (true) { auto edge = edge_stack.top(); edge_stack.pop(); bcc.insert(edge.first); bcc.insert(edge.second); if (edge.first == make_pair(x, y) && edge.second == make_pair(nx, ny)) { break; } } bcc_list.push_back(bcc); } } else if (dfn[nx][ny] < dfn[x][y]) { // 回边 edge_stack.push({{x, y}, {nx, ny}}); low[x][y] = min(low[x][y], dfn[nx][ny]); } } } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); cin >> n >> m; grid.resize(m, vector<int>(n)); for (int i = 0; i < m; ++i) { for (int j = 0; j < n; ++j) { cin >> grid[i][j]; if (grid[i][j] == 2) { bx = i; by = j; } } } // 步骤1:检测电源短路 if (has_power_short_circuit()) { cout << "Error" << endl; return 0; } // 步骤2:求解原始图的点双连通分量 dfn.resize(m, vector<int>(n, 0)); low.resize(m, vector<int>(n, 0)); tarjan(bx, by, -1, -1); // 处理栈中剩余的边(根节点所在的点双) if (!edge_stack.empty()) { set<pair<int, int>> bcc; while (!edge_stack.empty()) { auto edge = edge_stack.top(); edge_stack.pop(); bcc.insert(edge.first); bcc.insert(edge.second); } bcc_list.push_back(bcc); } // 步骤3:统计包含电池的点双中的灯泡,去重 set<pair<int, int>> valid_bulbs; for (const auto& bcc : bcc_list) { if (bcc.count({bx, by})) { for (const auto& p : bcc) { int x = p.first, y = p.second; if (grid[x][y] == 3) { valid_bulbs.insert(p); } } } } // 步骤4:输出结果 if (valid_bulbs.empty()) { cout << "Error" << endl; } else { cout << valid_bulbs.size() << endl; } return 0; } -
1@ 2008-08-02 13:47:03
这是我出的题...
怎么你们的程序都冗长... -
0@ 2015-06-03 22:44:41
5 5
1 1 1 3 1
1 0 1 0 1
1 3 1 0 1
1 0 1 0 1
1 1 1 2 1
为什么是2?短路判断完直接数接线? -
0@ 2013-08-21 22:15:43
行列坑爹啊,大家千万小心,别被题目猥琐欲为了!!
-
0@ 2012-11-02 23:07:24
咳咳,补充个数据范围:
3 -
0@ 2009-08-07 11:58:55
我就一个DFS,弱弱的数据,沙茶法则都可以秒杀,哎~~~~~~
-
0@ 2009-08-01 16:14:06
第30个ac,简单的dfs也可以秒杀
-
0@ 2009-07-28 22:27:15
........汗...
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
---|---|---|---|---|---|---|---|-
Accepted 有效得分:100 有效耗时:0ms
.....难得....第一次难度3的进前30....还一次ac秒杀......先用checkshort判断是否短路..再用checkopen判断是否开路...
最后用checknum找几个电灯泡在有电源的电路中...
三个函数大同小异..主要用foodfill... -
0@ 2009-07-26 17:01:11
这题目。。无语,我错误程序过了
-
0@ 2009-04-13 22:23:47
支持voyagec2的方法
1.一直删除所有的非零数,如果它的周围四个中有不少于3个0,直到不能删
统计剩下的灯泡
2.删掉那些灯泡,然后重复"一直删除所有的非零数,如果它的周围四个中有不少于3个0,直到不能删"
检测电池旁边是否有导线,有的话判定短路 -
0@ 2009-02-03 21:45:43
题质量不高.N,M=3 then begin flag:=false;map:=0; end;
end;
until flag;最后亮的灯泡就是修改了的电路中仍存在的灯泡
这么做一次AC -
0@ 2008-10-20 15:01:06
哦,原来灯泡短路和电路短路不同的概念!!!
先一遍dfs判断是否短路。
然后大家要千万注意行列的读法!!! -
0@ 2008-10-14 19:53:07
╭┓┏━━┓┏━┣━━┓╭┓ ┏┓ ┏━━┻━┓ ┣┳┏━━┓┃ ╯ ┃┏┣━┣━┓ ┏━━┓ ┃┃┃ ┃┗┳┗━┏╯╭┛ ┃ ┃ ┗━━┛ ┏┣┗━━╯┏┃━━╯┛┃ ┃ ┃┏━━━━┓ ┣╰┓╭┛┃┣┏━━┓┃ ┛━┛ ┏━━┓ 囧 ,┗╯┗━━┛┗┻┗━━╯┗━━━━╯╰╯ ╰┛ -
0@ 2008-10-07 20:40:28
简单的深搜加FLOODFILL而已
怎么就这么点人AC,无语了,一次AC庆贺下~~~~ -
0@ 2008-10-07 11:39:50
灯泡短路也算亮
汗,,他的灯泡什么灯泡来的。。
-
0@ 2008-10-07 09:28:20
这个题实在是让人升不起做的欲望....
灯泡短路也算亮.....
什么理论啊 -
0@ 2008-08-19 16:32:45
把行跟列搞反了,WA了无数次,前四个点居然长宽相等,检查了半天才发现.
5555555~~ -
0@ 2008-07-22 22:09:31
貌似样例2左边那个灯泡和导线并联啊,应该不会亮吧
-
0@ 2008-07-25 20:36:18
最后一个点...为什么老错...
-
0@ 2008-07-19 21:59:44
汗。。。灯泡短路也算亮,让我想挺久的。。