假设我们有两个大小相同的costs_from和costs_to列表,其中每个索引i代表一个城市。它正在从城市i到j的单向道路,其成本为costs_from [i] + costs_to [j]。我们还有一个边列表,其中每个边包含[x,y],表示从城市x到y已有单向道路。如果要从城市0到任何城市,我们必须找到建造必要道路的最低成本。
因此,如果输入像costs_from = [6,2,2,12] cost_to = [2,2,3,2] edge = [[0,3]],那么我们将输出为13从0到2的成本为9。之后,我们可以从2到1的成本为4。并且我们已经有从0到3的道路。所以总数为9 + 4 = 13。
为了解决这个问题,我们将遵循以下步骤-
n:=成本的大小
ret:= 0
定义两个映射边缘并变红
对于g中的所有项目:
在边缘[it [0]]的末尾插入[1]
在[red [1]]的末尾插入[0]
from_cost:= inf
定义一个访问过的集合,另一个可以访问的集合
定义一个函数dfs,这将需要一个数字i
将我插入访问
对于边[i]中的所有j,做
在po的末尾插入i
dfs(j)
如果我没有去过我并且无法到达,那么:
定义一个函数dfs2,这将需要一个数字i
如果拜访我,那么
返回真
如果我可以到达
返回假
将我标记为已访问并将我标记为可访问
ret:= true
对于所有红色的[i],做
ret:+ ret和dfs2(j)
返回ret
定义一个队列q
在可达中插入0,在q中插入0
当(q不为空)时,请执行以下操作:
如果我无法到达,则:
from_cost:= from_cost和costs_from [node]的最小值
将我插入可及范围,将我插入q
节点:= q的第一个元素
从q删除元素
对于边缘中的每个i [node]
global_min:= costs_from的最小元素
ret:= ret + from_cost-global_min
定义数组po
对于0到n范围内的i,执行
dfs(i)
反转数组po
对于每个我在po中,
最好:= inf
对于访问的每个j:
ret:= ret + global_min +最佳
最佳:=最佳和costs_to的最小值[j]
进行下一次迭代
如果我可以到达,则:
清除访问的数组
首字母:= dfs2(i)
如果initial为true,则:
返回ret
让我们看下面的实现以更好地理解-
#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