Alice has just graduated from wizard school, and wishes to cast a magic spell to celebrate. The magic spell contains certain focus points where magic needs to be concentrated, and some of these focus points contain magic crystals which serve as the spell’s energy source. Focus points can be linked through directed runes, which channel magic flow from one focus point to another.
You are given a integer n denoting the number of focus points and an array of integers crystals where crystals[i] indicates a focus point which holds a magic crystal. You are also given two integer arrays flowFrom and flowTo, which represent the existing directed runes. The ith rune allows magic to freely flow from focus point flowFrom[i] to focus point flowTo[i].
You need to find the number of directed runes Alice must add to her spell, such that each focus point either:
Contains a magic crystal.
Receives magic flow from another focus point.
Return the minimum number of directed runes that she should add.
We want every node to either have a crystal or be reachable from a crystal. BFS from crystals marks all reachable nodes. For the rest, we use DFS to find nodes that need new runes, processing in reverse topological order to minimize additions.
classSolution {
public:int minRunesToAdd(int n, vector<int>& crystals, vector<int>& flowFrom, vector<int>& flowTo) {
vector<vector<int>> g(n);
for (int i =0; i < flowFrom.size(); ++i) {
g[flowFrom[i]].push_back(flowTo[i]);
}
vector<int> vis(n, 0), seq;
queue<int> q;
for (int i : crystals) {
vis[i] =1;
q.push(i);
}
auto bfs = [&](queue<int>& q) {
while (!q.empty()) {
int a = q.front(); q.pop();
for (int b : g[a]) {
if (vis[b] ==1) continue;
vis[b] =1;
q.push(b);
}
}
};
bfs(q);
function<void(int)> dfs = [&](int a) {
vis[a] =2;
for (int b : g[a]) {
if (vis[b] >0) continue;
dfs(b);
}
seq.push_back(a);
};
for (int i =0; i < n; ++i) {
if (vis[i] ==0) dfs(i);
}
int ans =0;
for (int i = seq.size() -1; i >=0; --i) {
int a = seq[i];
if (vis[a] ==2) {
vis[a] =1;
queue<int> nq;
nq.push(a);
bfs(nq);
++ans;
}
}
return ans;
}
};
classSolution {
privatelateinitvar vis: IntArray
privatelateinitvar g: Array<MutableList<Int>>
privateval seq = mutableListOf<Int>()
funminRunesToAdd(n: Int, crystals: IntArray, flowFrom: IntArray, flowTo: IntArray): Int {
g = Array(n) { mutableListOf() }
for (i in flowFrom.indices) {
g[flowFrom[i]].add(flowTo[i])
}
vis = IntArray(n)
val q = ArrayDeque<Int>()
for (i in crystals) {
vis[i] = 1 q.add(i)
}
bfs(q)
for (i in0 until n) {
if (vis[i] ==0) {
dfs(i)
}
}
var ans = 0for (i in seq.size - 1 downTo 0) {
val a = seq[i]
if (vis[a] ==2) {
vis[a] = 1val nq = ArrayDeque<Int>()
nq.add(a)
bfs(nq)
ans++ }
}
return ans
}
privatefunbfs(q: ArrayDeque<Int>) {
while (q.isNotEmpty()) {
val a = q.removeFirst()
for (b in g[a]) {
if (vis[b] ==1) continue vis[b] = 1 q.add(b)
}
}
}
privatefundfs(a: Int) {
vis[a] = 2for (b in g[a]) {
if (vis[b] > 0) continue dfs(b)
}
seq.add(a)
}
}
classSolution:
defminRunesToAdd(self, n: int, crystals: list[int], flowFrom: list[int], flowTo: list[int]) -> int:
g = [[] for _ in range(n)]
for a, b in zip(flowFrom, flowTo):
g[a].append(b)
vis = [0] * n
seq: list[int] = []
q: list[int] = []
for i in crystals:
vis[i] =1 q.append(i)
defbfs(q: list[int]):
while q:
a = q.pop(0)
for b in g[a]:
if vis[b] ==1:
continue vis[b] =1 q.append(b)
bfs(q)
defdfs(a: int):
vis[a] =2for b in g[a]:
if vis[b] >0:
continue dfs(b)
seq.append(a)
for i in range(n):
if vis[i] ==0:
dfs(i)
ans =0for a in reversed(seq):
if vis[a] ==2:
vis[a] =1 nq = [a]
bfs(nq)
ans +=1return ans