📅  最后修改于: 2023-12-03 15:12:47.449000             🧑  作者: Mango
这道问题涉及到的是有向图的连通性问题。具体来说,给出一个由N个节点和M条有向边构成的图,同时给出每个节点是否有门。每个门可以从该节点开始遍历整个有向图,并且不能经过不带门的节点。求图中从至少一个门出发能够到达的节点数。
可以采用深度优先搜索(DFS)来遍历整个图,同时仅仅遍历有门的节点。类似于标准的DFS算法,但是需要增加一个参数来保存当前搜索的起始节点。
在DFS的过程中,需要递归地访问当前节点的邻居节点。如果邻居节点有门,就将其作为起始节点继续搜索。否则就不继续搜索,直接回溯到上一个节点。在DFS的过程中,需要使用一个数组来记录每个节点是否已经被访问过。
最终,统计有多少节点被访问过即可。
import java.util.ArrayList;
import java.util.Scanner;
public class Main {
static boolean[] vis;
static ArrayList<ArrayList<Integer>> graph;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int m = sc.nextInt();
graph = new ArrayList<>();
vis = new boolean[n+1];
for (int i = 0; i <= n; i++) {
graph.add(new ArrayList<>());
}
for (int i = 0; i < m; i++) {
int u = sc.nextInt();
int v = sc.nextInt();
graph.get(u).add(v);
}
boolean[] hasDoor = new boolean[n+1];
for (int i = 1; i <= n; i++) {
int x = sc.nextInt();
hasDoor[i] = x == 1;
}
int ans = 0;
for (int i = 1; i <= n; i++) {
if (hasDoor[i] && !vis[i]) {
ans += dfs(i, hasDoor);
}
}
System.out.println(ans);
}
private static int dfs(int u, boolean[] hasDoor) {
vis[u] = true;
int res = 1;
for (int v : graph.get(u)) {
if (!vis[v] && hasDoor[v]) {
res += dfs(v, hasDoor);
}
}
return res;
}
}
该算法使用DFS遍历整个图,每个节点最多被遍历一次。因此,时间复杂度为O(N+M)。其中,N和M分别为图的节点和边的数量。