wenLiu.vercel

May 31, 2024

Graph Theory

Graph Theory

1.1 Graph Construction

1.1.1 Adjacency List with Edge Weights

import java.util.ArrayList;import java.util.List;import java.util.Scanner;public class Main {    // Define the adjacency list representation of the graph    static List<int[]>[] g;    // Number of nodes    static int n;    // Array to store some state or result    static int[] f;    public static void main(String[] args) {        Scanner scanner = new Scanner(System.in);                // Read the number of nodes        n = scanner.nextInt();                // Initialize the adjacency list        g = new ArrayList[n + 1];        for (int i = 1; i <= n; i++) {            g[i] = new ArrayList<>();        }                // Initialize the state array        f = new int[n + 1];        // Read the edges and construct the graph        for (int i = 1; i < n; i++) {            int a = scanner.nextInt(); // One endpoint of the edge            int b = scanner.nextInt(); // The other endpoint of the edge            int c = scanner.nextInt(); // The weight of the edge            // Add the undirected edge to the adjacency list            g[a].add(new int[]{b, c});            g[b].add(new int[]{a, c});        }    }    // Depth-first search (DFS) to traverse the graph    static void dfs(int u, int fa) {        // Traverse all adjacent nodes of node u        for (int[] pair : g[u]) {            int x = pair[0]; // Adjacent node            int w = pair[1]; // Weight of the edge            // If the adjacent node is the parent node, skip it (to avoid going back)            if (x == fa) continue;            // Recursively traverse the adjacent nodes            dfs(x, u);            // Additional logic can be added here        }    }}

1.1.2 Adjacency List with Node Weights

import java.util.Scanner;import java.util.ArrayList;public class Main {    // Define a constant N for the maximum number of nodes    static final int N = 100010;    // Used to store the adjacency list representation of the graph    static ArrayList<Integer>[] g = new ArrayList[N];    // Used to store the weights of the nodes    static int[] w = new int[N];    // Depth-first search (DFS) to traverse the graph    static void dfs(int u, int fa) {        // Handle the operations for node u        // Traverse all adjacent nodes of node u        for (int x : g[u]) {            // If the adjacent node is the parent node, skip it (to avoid going back)            if (x == fa)                continue;            // Recursively traverse the adjacent nodes            dfs(x, u);            // Handle the operations after returning from the child node        }    }    public static void main(String[] args) {        int n, m;        Scanner scanner = new Scanner(System.in);        // Read the number of nodes n and the number of edges m        n = scanner.nextInt();        m = scanner.nextInt();        // Initialize the adjacency list        for (int i = 1; i <= n; i++) {            g[i] = new ArrayList<>();        }        // Read the edges and construct the graph        for (int i = 0; i < m; i++) {            int a, b;            a = scanner.nextInt();            b = scanner.nextInt();            g[a].add(b);  // Add an edge from a to b        }        // Read the weight of each node        for (int i = 1; i <= n; i++) {            w[i] = scanner.nextInt();        }        // DFS can be called here, for example, starting from node 1        // dfs(1, -1);    }}

1.1.3 Discretization for Graph Construction

Points have a very large range (e.g., [−109, 109]) or contain negative points. Points are not numbers but strings, and there is a conversion relationship between the strings.

import java.util.*;public class Main {    public static void main(String[] args) {        // Define a constant N for the possible maximum number of nodes        int N = 100010;                // Define a hash table to store the edges and their weights between nodes        // The key is the node, the value is a list containing the target nodes and edge weights        Map<Integer, List<Map.Entry<Integer, Integer>>> path = new HashMap<>();                // Example: Add an edge from node u to node v with a weight of w        int u = 1, v = 2, w = 3;                // If the hash table does not contain the key u, initialize its value to a new ArrayList        if (!path.containsKey(u)) {            path.put(u, new ArrayList<>());        }                // Add the edge (v, w) to the list of node u        path.get(u).add(new AbstractMap.SimpleEntry<>(v, w));                // Example: Traverse all adjacent nodes and edge weights of node        int node = 1;                // If the hash table contains the key node, traverse it        if (path.containsKey(node)) {            for (Map.Entry<Integer, Integer> entry : path.get(node)) {                int target = entry.getKey();  // Adjacent node                int weight = entry.getValue(); // Weight of the edge                // Process, for example, print or other logic                System.out.println("The edge weight from node " + node + " to node " + target + " is " + weight);            }        }    }}

1.2 Topological Sorting

Used to determine if there is a cycle in a directed graph.

LeetCode 207. Course Schedule

Topological sorting template problem.
Build a graph based on dependencies: if course a must be taken before course b, then there is a directed edge b->a. If all courses can be completed, it means a topological order exists.

import java.util.*;class Solution {    public boolean canFinish(int numCourses, int[][] prerequisites) {        // Create an adjacency list representation of the graph        List<List<Integer>> g = new ArrayList<>();        for (int i = 0; i < numCourses; i++) {            g.add(new ArrayList<>()); // Initialize adjacency list for each node        }                // Create an array to store the in-degree of each node        int[] d = new int[numCourses];                // Build the graph and calculate the in-degree of each node        for (int[] p : prerequisites) {            g.get(p[1]).add(p[0]); // Add an edge from node p[1] to node p[0]            d[p[0]]++; // Increment the in-degree of node p[0]        }                // Initialize a queue for BFS        Queue<Integer> q = new LinkedList<>();        int cnt = 0; // Counter to record the number of nodes that can be traversed                // Add all nodes with in-degree 0 to the queue        for (int i = 0; i < numCourses; i++) {            if (d[i] == 0) {                q.offer(i);                cnt++;            }        }                // Perform BFS to process nodes        while (!q.isEmpty()) {            int t = q.poll(); // Remove a node from the queue            for (int v : g.get(t)) { // Traverse all nodes dependent on node t                d[v]--; // Decrement the in-degree of the dependent node                if (d[v] == 0) { // If the in-degree of the dependent node becomes 0, add it to the queue                    q.offer(v);                    cnt++;                }            }        }                // If the number of processed nodes equals the total number of nodes, it means all nodes can be traversed; otherwise, they cannot        return cnt == numCourses;    }}