时间轴
时间轴
2025-11-07
init
题目:
DFS+最小堆+懒删除
下面这个代码会 WA,原因是维护了每个结点能到达的所有结点为一个最小堆,如果使某个结点下线,只从所有能到达该结点的堆中懒删除了该结点,而没有考虑需要从该节点经过才能到达的结点,这类结点也不能可达。而且:电网的结构是固定的;离线(非运行)的节点仍然属于其所在的电网,且离线操作不会改变电网的连接性。
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117 | using std::vector;using std::unordered_set;using std::priority_queue;using std::unordered_map;using std::stack;typedef priority_queue<int, vector<int>, std::greater<int> > MinHeap;class Solution { public: vector<int> processQueries(int c, vector<vector<int> > &connections, vector<vector<int> > &queries) { vector<bool> work_states = vector<bool>(c, true); vector<MinHeap> neighbors_heap = vector<MinHeap>(c, MinHeap()); vector<unordered_set<int> > to_be_deleted = vector<unordered_set<int> >(c); unordered_map<int, vector<int> > graph; vector<int> res; int i = 0, j = 0, n, connection_size = connections.size(); int p_stat1, p_stat2; // 建图 for (i = 0; i < c; i++) { // 编号从0到c-1 graph[i] = vector<int>(); } for (i = 0; i < connection_size; i++) { p_stat1 = connections[i][0] - 1; // 从0开始编号 p_stat2 = connections[i][1] - 1; graph[p_stat1].push_back(p_stat2); graph[p_stat2].push_back(p_stat1); } // 填充neighbors_heap int top; vector<bool> visited = vector<bool>(c, false); vector<vector<int> > graph_components; for (i = 0; i < c; i++) { // 深度优先遍历 if (visited[i]) { continue; } stack<int> st; st.push(i); vector<int> curr_graph; while (!st.empty()) { top = st.top(); st.pop(); if (!visited[top]) { visited[top] = true; curr_graph.push_back(top); } for (int node : graph[top]) { if (!visited[node]) { st.push(node); } } } graph_components.push_back(curr_graph); } for (vector<int> v : graph_components) { //图的每个连通分量 n = v.size(); for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { if (j == i) { continue; } neighbors_heap[v[i]].push(v[j]); } } } int query_size = queries.size(); int ops, p_stat; bool flag; for (i = 0; i < query_size; i++) { ops = queries[i][0]; p_stat = queries[i][1] - 1; if (ops == 1) { // maintence if (work_states[p_stat]) { // p_stat在线,自行解决 res.push_back(p_stat + 1); } else { //它的neighbor_heap中最小的 flag = true; while (!neighbors_heap[p_stat].empty()) { top = neighbors_heap[p_stat].top(); if (!to_be_deleted[p_stat].count(top)) { // 不需要删除 res.push_back(top + 1); flag = false; break; } else { neighbors_heap[p_stat].pop(); to_be_deleted[p_stat].erase(top); } } if (flag) { res.push_back(-1); } } } else if (ops == 2) { // goes offline work_states[p_stat] = false; // p_stat标记为offline for (int ps : graph[p_stat]) { // 所有指向p_stat标记为删除 to_be_deleted[ps].insert(p_stat); } } } return res; }}; |
官方正解:
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576 | class Vertex {public: int vertexId; bool offline = false; int powerGridId = -1; Vertex() {} Vertex(int id) : vertexId(id) {}};using PowerGrid = priority_queue<int, vector<int>, greater<int>>;using Graph = vector<vector<int>>;class Solution {private: vector<Vertex> vertices = vector<Vertex>(); void traverse(Vertex& u, int powerGridId, PowerGrid& powerGrid, Graph& graph) { u.powerGridId = powerGridId; powerGrid.push(u.vertexId); for (int vid : graph[u.vertexId]) { Vertex& v = vertices[vid]; if (v.powerGridId == -1) traverse(v, powerGridId, powerGrid, graph); } }public: vector<int> processQueries(int c, vector<vector<int>>& connections, vector<vector<int>>& queries) { Graph graph(c + 1); vertices.resize(c + 1); for (int i = 1; i <= c; i++) { vertices[i] = Vertex(i); } for (auto& conn : connections) { graph[conn.at(0)].push_back(conn.at(1)); graph[conn.at(1)].push_back(conn.at(0)); } vector<PowerGrid> powerGrids; for (int i = 1, powerGridId = 0; i <= c; i++) { auto& v = vertices[i]; if (v.powerGridId == -1) { PowerGrid powerGrid; traverse(v, powerGridId, powerGrid, graph); powerGrids.push_back(powerGrid); powerGridId++; } } vector<int> ans; for (auto& q : queries) { int op = q.at(0), x = q.at(1); if (op == 1) { if (!vertices[x].offline) { ans.push_back(x); } else { auto& powerGrid = powerGrids[vertices[x].powerGridId]; while (!powerGrid.empty() && vertices[powerGrid.top()].offline) { powerGrid.pop(); } ans.push_back(!powerGrid.empty() ? powerGrid.top() : -1); } } else if (op == 2) { vertices[x].offline = true; } } return ans; }}; |
并查集
这个方法有点难想到:
困难点:操作是在线进行的,下线操作会影响后续查询。但题目说电网结构固定,即下线不会改变连接性。于是,可以反向思考:如果我们把操作从后往前看,“下线”就会变成“重新上线”!所以算法采用了一个反向过程:
- 先预处理所有节点的最终状态(哪些在最后是下线的)。
- 然后从最后一个操作往前处理。
- 把“下线”视作“重新上线”。
- 用并查集(DSU)维护每个电网中的最小在线编号。官方解法:
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980 | class DSU {public: vector<int> parent; DSU(int size) { parent.resize(size); iota(parent.begin(), parent.end(), 0); } int find(int x) { return parent[x] == x ? x : parent[x] = find(parent[x]); } void join(int u, int v) { parent[find(v)] = find(u); }};class Solution {public: vector<int> processQueries(int c, vector<vector<int>>& connections, vector<vector<int>>& queries) { DSU dsu(c + 1); for (auto& p : connections) { dsu.join(p[0], p[1]); } vector<bool> online(c + 1, true); vector<int> offlineCounts(c + 1, 0); unordered_map<int, int> minimumOnlineStations; for (auto& q : queries) { int op = q[0], x = q[1]; if (op == 2) { online[x] = false; offlineCounts[x]++; } } for (int i = 1; i <= c; i++) { int root = dsu.find(i); if (!minimumOnlineStations.count(root)) { minimumOnlineStations[root] = -1; } int station = minimumOnlineStations[root]; if (online[i]) { if (station == -1 || station > i) { minimumOnlineStations[root] = i; } } } vector<int> ans; for (int i = (int)queries.size() - 1; i >= 0; i--) { int op = queries[i][0], x = queries[i][1]; int root = dsu.find(x); int station = minimumOnlineStations[root]; if (op == 1) { if (online[x]) { ans.push_back(x); } else { ans.push_back(station); } } if (op == 2) { if (offlineCounts[x] > 1) { offlineCounts[x]--; } else { online[x] = true; if (station == -1 || station > x) { minimumOnlineStations[root] = x; } } } } reverse(ans.begin(), ans.end()); return ans; }}; |
