สมมติว่าเรามีสองลิสต์ costs_from และ costs_to ที่มีขนาดเท่ากัน โดยดัชนี i แทนเมืองหนึ่ง การสร้างถนนทางเดียวจากเมือง i ไป j มีค่าใช้จ่ายเท่ากับ costs_from[i] + costs_to[j] นอกจากนี้ยังมีลิสต์ edges ที่แต่ละขอบมีรูปแบบ [x, y] แสดงว่ามีถนนทางเดียวจากเมือง x ไป y อยู่แล้ว หากเราต้องการเดินทางไปยังเมืองใดก็ได้จากเมือง 0 เราต้องหาต้นทุนขั้นต่ำในการสร้างถนนที่จำเป็น
ตัวอย่างเช่น หากอินพุตคือ costs_from = [6, 2, 2, 12], costs_to = [2, 2, 3, 2], edges = [[0, 3]] ผลลัพธ์จะเป็น 13 เนื่องจากเราสามารถเดินทางจาก 0 ไป 2 ด้วยต้นทุน 9 จากนั้นเดินทางจาก 2 ไป 1 ด้วยต้นทุน 4 และเรามีถนนจาก 0 ไป 3 อยู่แล้ว ดังนั้นรวมเป็น 9 + 4 = 13
ขั้นตอนการแก้ปัญหา
n:= ขนาดของcosts_fromret:= 0- กำหนดแมป
edgesและredgesสำหรับกราฟและกราฟย้อนกลับ - สำหรับทุก
itในg:- เพิ่ม
it[1]เข้าedges[it[0]] - เพิ่ม
it[0]เข้าredges[it[1]]
- เพิ่ม
from_cost:= infinity- กำหนดเซต
visitedและreachable - ฟังก์ชัน
dfs(i):- ถ้า
iยังไม่ถูกเยี่ยมชมและไม่ถึงได้:- เพิ่ม
iเข้าvisited - สำหรับทุก
jในedges[i]เรียกdfs(j) - เพิ่ม
iเข้าpo(post-order)
- เพิ่ม
- ถ้า
- ฟังก์ชัน
dfs2(i):- ถ้า
iอยู่ในvisitedคืนtrue - ถ้า
iอยู่ในreachableคืนfalse - ทำเครื่องหมาย
iว่าเยี่ยมชมและถึงได้แล้ว ret := true- สำหรับทุก
jในredges[i]คำนวณret &= dfs2(j) - คืน
ret
- ถ้า
- คิว
qเริ่มจากโหนด 0 เพื่อหาโหนดที่ถึงได้จากเมือง 0 - คำนวณ
from_costเป็นค่าcosts_fromต่ำสุดของโหนดที่ถึงได้ global_min:= ค่าcosts_fromต่ำสุดของทุกเมืองret := ret + from_cost - global_min- สร้างอาเรย์
poโดยเรียกdfs(i)สำหรับทุกiแล้วกลับลำดับ - สำหรับแต่ละ
iในpo:- ถ้า
iถึงได้แล้ว ข้ามไป - เคลียร์
visitedเรียกinitial = dfs2(i) - ถ้า
initialเป็นจริง:- หา
best= ค่าcosts_toต่ำสุดในvisited ret := ret + global_min + best
- หา
- ถ้า
- คืนค่า
ret
ตัวอย่างโค้ด C++
#include <bits/stdc++.h>
using namespace std;
class Solution {
public:
int solve(vector<int>& costs_from, vector<int>& costs_to, vector<vector<int>>& g) {
int n = costs_from.size();
int ret = 0;
map<int, vector<int>> edges;
map<int, vector<int>> redges;
for (auto& it : g) {
edges[it[0]].push_back(it[1]);
redges[it[1]].push_back(it[0]);
}
int from_cost = INT_MAX;
set<int> visited;
set<int> reachable;
queue<int> q;
reachable.insert(0);
q.push(0);
while (!q.empty()) {
int node = q.front();
q.pop();
for (int i : edges[node]) {
if (!reachable.count(i)) {
reachable.insert(i);
q.push(i);
}
}
from_cost = min(from_cost, costs_from[node]);
}
int global_min = *min_element(costs_from.begin(), costs_from.end());
ret += from_cost - global_min;
vector<int> po;
function<void(int)> dfs = [&](int i) {
if (!visited.count(i) && !reachable.count(i)) {
visited.insert(i);
for (int j : edges[i]) {
dfs(j);
}
po.push_back(i);
}
};
for (int i = 0; i < n; i++) dfs(i);
reverse(po.begin(), po.end());
function<bool(int)> dfs2 = [&](int i) {
if (visited.count(i)) return true;
if (reachable.count(i)) return false;
visited.insert(i);
reachable.insert(i);
bool ret = true;
for (int j : redges[i]) {
ret &= dfs2(j);
}
return ret;
};
for (int i : po) {
if (reachable.count(i)) continue;
visited.clear();
bool initial = dfs2(i);
if (initial) {
int best = INT_MAX;
for (int j : visited) {
best = min(best, costs_to[j]);
}
ret += global_min + best;
}
}
return ret;
}
};
int solve(vector<int>& costs_from, vector<int>& costs_to, vector<vector<int>>& edges) {
return (new Solution())->solve(costs_from, costs_to, edges);
}
int main() {
vector<int> costs_from = {6, 2, 2, 12};
vector<int> costs_to = {2, 2, 3, 2};
vector<vector<int>> edges = {{0, 3}};
cout << solve(costs_from, costs_to, edges);
}
อินพุต
{6, 2, 2, 12}, {2, 2, 3, 2}, {{0, 3}}
เอาต์พุต
13