图的常用算法(代码)

1.拓扑排序

public boolean Topology(int n, int[][] edges) {
    List<Integer>[] g = new ArrayList[n];
    Arrays.setAll(g, e -> new ArrayList<Integer>());
    int[] count = new int[n];
    for (int[] e : edges) {
        int v = e[0], u = e[1]; //v是起始,u是终点
        g[v].add(u);
        count[u]++;
    }
    Queue<Integer> queue = new LinkedList<>();
    for (int i = 0; i < n; i++) {
        if (count[i] == 0) queue.add(i);
    }
    while (!queue.isEmpty()) {
        int v = queue.poll();
        for (int u : g[v]) {
            count[u]--;
            if (count[u] == 0) queue.add(u);
        }
    }
    for (int num : count) {
        if (num != 0) return false;
    }
    return true;
}

2.prim算法(堆优化)

public int prim(int n, int[][] edges) {
    List<int[]>[] g = new ArrayList[n];
    Arrays.setAll(g, e -> new ArrayList<int[]>());
    for (int[] e : edges) {
        int u = e[0], v = e[1], cnt = e[2];
        g[u].add(new int[]{v, cnt});
        g[v].add(new int[]{u, cnt});
    }
    HashSet<Integer> visited = new HashSet<>();
    PriorityQueue<int[]> pq = new PriorityQueue<>((a, b) -> a[1] - b[1]);
    pq.offer(new int[]{0,0});
    int res = 0;
    while (visited.size() < n) {
        int[] p = pq.poll();
        if (visited.contains(p[0])) continue;
        visited.add(p[0]);
        res += p[1];
        for (int[] u : g[p[0]]) {
            if (u[0] != p[0]) {
                pq.offer(u);
            }
        }
    }
    return res;
}

3.Kruskal算法

public int kruskal(int n, int[][] edges) {
    UnionJoin unionJoin = new UnionJoin(n);
    int res = 0;
    for (int[] item : edges) {
        if (unionJoin.union(item[0], item[1])) {
            res += item[2];
        }
    }
    return res;
}

class UnionJoin {
    int[] parent;
    public UnionJoin(int n) {
        parent = new int[n];
        for (int i=0; i<n; i++) {
            parent[i] = i;
        }
    }

    public boolean union(int i, int j) {
        int parentI = getParent(i);
        int parentJ = getParent(j);
        if (parentI == parentJ) return false;
        parent[parentI] = parentJ;
        return true;
    }

    public int getParent(int i) {
        if (parent[i] != i) parent[i] = getParent(parent[i]);
        return parent[i];
    }
}

4.dijkstra算法(堆优化)

public int[] research(int[][] edges, int n) {
    List<int[]>[] g = new ArrayList[n];
    Arrays.setAll(g, e -> new ArrayList<int[]>());
    for (int[] e : edges) {
        int u = e[0], v = e[1], cnt = e[2];
        g[u].add(new int[]{v, cnt});
        g[v].add(new int[]{u, cnt});
    }

    int[] dist = dijkstra(g, 0);
    return dist;
}

private int[] dijkstra(List<int[]>[] g, int start) {
    int[] dist = new int[g.length];
    Arrays.fill(dist, Integer.MAX_VALUE);
    dist[start] = 0;
    PriorityQueue<int[]> pq = new PriorityQueue<>((a, b) -> a[1] - b[1]);
    pq.offer(new int[]{start, 0});
    while (!pq.isEmpty()) {
        int[] p = pq.poll();
        int x = p[0], d = p[1];
        if (d > dist[x]) continue;
        for (int[] e :g[x]) {
            int y = e[0];
            int newDist = d + e[1];
            if (newDist < dist[y]) {
                dist[y] = newDist;
                pq.offer(new int[]{y, newDist});
            }
        }
    }
    return dist;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值