สมมติว่าเรามีรายการ cost_from และ cost_to สองรายการที่มีขนาดเท่ากัน โดยแต่ละดัชนี i แสดงถึงเมือง กำลังสร้างถนนเดินรถทางเดียวจากเมือง i ไปยัง j และค่าใช้จ่ายคือ cost_from[i] + cost_to[j] นอกจากนี้เรายังมีรายการขอบที่แต่ละขอบมี [x, y] ระบุว่ามีถนนเดินรถทางเดียวจากเมือง x ถึง y แล้ว หากเราต้องการไปเมืองใด ๆ จากเมือง 0 เราต้องหาต้นทุนขั้นต่ำเพื่อสร้างถนนที่จำเป็น
ดังนั้นหากอินพุตเป็นเหมือน cost_from =[6, 2, 2, 12] cost_to =[2, 2, 3, 2] edge =[[0, 3]] ผลลัพธ์จะเป็น 13 อย่างที่เราสามารถทำได้ จาก 0 ถึง 2 ในราคา 9 หลังจากนั้น เราสามารถไปจาก 2 เป็น 1 ในราคา 4 และเรามีถนนที่จะไปที่ 3 จาก 0 แล้ว รวมเป็น 9 + 4 =13พี>
เพื่อแก้ปัญหานี้ เราจะทำตามขั้นตอนเหล่านี้ -
- n :=ขนาดของ cost_from
- ret :=0
- กำหนดสองขอบและขอบของแผนที่
- สำหรับรายการทั้งหมดใน g:
- ใส่มัน[1] ที่ส่วนท้ายของขอบ[it[0]]
- แทรก it[0] ที่ส่วนท้ายของสีแดง[it[1]]
- from_cost :=inf
- กำหนดหนึ่งชุดที่เข้าชมและอีกชุดที่เข้าถึงได้
- กำหนดฟังก์ชัน dfs ซึ่งจะใช้ตัวเลข i
- ถ้าฉันไม่ได้มาเยี่ยมและไม่สามารถเข้าถึงได้ ดังนั้น:
- แทรกฉันเข้าไปในการเยี่ยมชม
- สำหรับ j in edge[i] ทั้งหมด ให้ทำ
- dfs(j)
- ใส่ i ต่อท้าย po
- ถ้าฉันไม่ได้มาเยี่ยมและไม่สามารถเข้าถึงได้ ดังนั้น:
- กำหนดฟังก์ชัน dfs2 ซึ่งจะใช้ตัวเลข i
- ถ้าฉันมาเยี่ยมแล้ว
- คืนค่าจริง
- ถ้าฉันสามารถเข้าถึงได้
- คืนค่าเท็จ
- ทำเครื่องหมายว่าเยี่ยมชมแล้วและทำเครื่องหมายว่าเข้าถึงได้
- ret :=true
- สำหรับ j ใน redges[i], do
- ret :+ ret และ dfs2(j)
- คืนสินค้า
- กำหนดหนึ่งคิว q
- แทรก 0 เข้าไปที่เข้าถึงได้ และแทรก 0 ลงใน q
- ในขณะที่ (q ไม่ว่าง) ให้ทำ:
- โหนด :=องค์ประกอบแรกของ q
- ลบองค์ประกอบออกจาก q
- สำหรับแต่ละ i ใน edge[node]
- หากฉันไม่สามารถเข้าถึงได้แล้ว:
- แทรก i เข้าไป แทรก i เข้าไปใน q
- from_cost :=ขั้นต่ำของ from_cost และ cost_from[node]
- หากฉันไม่สามารถเข้าถึงได้แล้ว:
- global_min :=องค์ประกอบขั้นต่ำของ cost_from
- ret :=ret + from_cost - global_min
- กำหนดอาร์เรย์ po
- สำหรับ i ในช่วง 0 ถึง n ให้ทำ
- dfs(i)
- ย้อนกลับอาร์เรย์ po
- สำหรับแต่ละ i ใน po ทำ
- ถ้าฉันสามารถเข้าถึงได้แล้ว:
- ติดตามตอนต่อไป
- ล้างอาร์เรย์ที่เข้าชม
- ค่าเริ่มต้น :=dfs2(i)
- ถ้าเริ่มต้นเป็นจริง ดังนั้น:
- ดีที่สุด :=inf
- สำหรับแต่ละ j ในการเยี่ยมชม:
- ดีที่สุด :=ขั้นต่ำสุดและ cost_to[j]
- ret :=ret + global_min + ดีที่สุด
- ถ้าฉันสามารถเข้าถึงได้แล้ว:
- คืนสินค้า
ให้เราดูการใช้งานต่อไปนี้เพื่อความเข้าใจที่ดีขึ้น -
ตัวอย่าง
#include
using namespace std;
class Solution {
public:
int solve(vector& costs_from, vector& costs_to, vector>& g) {
int n = costs_from.size();
int ret = 0;
map> edges;
map> 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 visited;
set reachable;
queue 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 po;
function dfs;
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 dfs2;
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& costs_from, vector& costs_to, vector>& edges) {
return (new Solution())->solve(costs_from, costs_to, edges);
}
int main(){
vector costs_from = {6, 2, 2, 12};
vector costs_to = {2, 2, 3, 2};
vector> edges = {{0, 3}};
cout << solve(costs_from, costs_to, edges);
} อินพุต
{6, 2, 2, 12}, {2, 2, 3, 2}, {{0, 3}} ผลลัพธ์
13