📜  门|门CS 2011 |问题 28(1)

📅  最后修改于: 2023-12-03 15:12:47.449000             🧑  作者: Mango

门|门CS 2011 |问题 28

这道问题涉及到的是有向图的连通性问题。具体来说,给出一个由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分别为图的节点和边的数量。