第三章图论(六)

最小生成树的扩展应用

在这里插入图片描述
例题:新的开始
在这里插入图片描述
【输入样例】
4
5
4
4
3
0 2 2 2
2 0 3 3
2 3 0 4
2 3 4 0
【输出样例】
9
在这里插入图片描述
————————————————————————————————————————————————————

import java.util.Arrays;
import java.util.Scanner;

public class Main {
    static int INF = Integer.MAX_VALUE >> 1;
    static int N = 310;
    static int n;
    static int[][] w = new int[N][N];
    static int[] dist = new int[N];
    static boolean[] st = new boolean[N];

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        n = sc.nextInt();
        for (int i = 1; i <= n; i++) {
            w[0][i] = sc.nextInt();
            w[i][0] = w[0][i];
        }
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= n; j++) {
                w[i][j] = sc.nextInt();
            }
        }
        System.out.println(prim());
    }

    private static int prim() {
        Arrays.fill(dist, INF);
        dist[0] = 0;
        int res = 0;
        for (int i = 0; i < n + 1; i++) {
            int t = -1;
            for (int j = 0; j <= n; j++) {
                if (!st[j] && (t == -1 || dist[t] > dist[j])) {
                    t = j;
                }
            }
            res += dist[t];
            st[t] = true;
            for (int j = 0; j <= n; j++) {
                dist[j] = Math.min(dist[j], w[t][j]);
            }
        }
        return res;
    }
}

例题:北极通讯网络
在这里插入图片描述

import java.util.Arrays;
import java.util.Comparator;
import java.util.Scanner;

public class Main {
    static int INF = Integer.MAX_VALUE >> 1;
    static int N = 510;
    static int M = N * N / 2;
    static int n;
    static int k;
    static int m;
    static Edge[] e = new Edge[M];
    static Pair[] q = new Pair[M];
    static int[] p = new int[N];

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        n = sc.nextInt();
        k = sc.nextInt();
        for (int i = 0; i < n; i++) {
            int x = sc.nextInt();
            int y = sc.nextInt();
            q[i] = new Pair(x, y);
        }
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < i; j++) {
                e[m++] = new Edge(i, j, get_dist(q[i], q[j]));
            }
        }
        Arrays.sort(e, 0, m, new Comparator<Edge>() {
            @Override
            public int compare(Edge o1, Edge o2) {
                if (o1.w <= o2.w) {
                    return -1;
                } else {
                    return 1;
                }
            }
        });
        for (int i = 0; i < n; i++) {
            p[i] = i;
        }
        int cnt = n;
        double res = 0;
        for (int i = 0; i < m; i++) {
            if (cnt <= k) break;
            int a = find(e[i].a);
            int b = find(e[i].b);
            double w = e[i].w;
            if (a != b) {
                p[a] = b;
                cnt--;
                res = w;
            }
        }
        System.out.printf("%.2f\n", res);
    }

    private static int find(int x) {
        if (p[x] != x) p[x] = find(p[x]);
        return p[x];
    }

    private static double get_dist(Pair a, Pair b) {
        int dx = a.x - b.x;
        int dy = a.y - b.y;
        return Math.sqrt(dx * dx + dy * dy);
    }
}
class Pair{
    int x;
    int y;

    public Pair(int x, int y) {
        this.x = x;
        this.y = y;
    }
}
class Edge{
    int a;
    int b;
    double w;

    public Edge(int a, int b, double w) {
        this.a = a;
        this.b = b;
        this.w = w;
    }
}

例题:346. 走廊泼水节
在这里插入图片描述

import java.util.Arrays;
import java.util.Comparator;
import java.util.Scanner;

public class Main {
    static int N = 6010;
    static int n;
    static Edge[] e = new Edge[N];
    static int[] p = new int[N];
    static int[] size = new int[N];

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int T = sc.nextInt();
        while (T-- > 0) {
            n = sc.nextInt();
            for (int i = 0; i < n - 1; i++) {
                int a = sc.nextInt();
                int b = sc.nextInt();
                int w = sc.nextInt();
                e[i] = new Edge(a, b, w);
            }
            Arrays.sort(e, 0, n - 1, new Comparator<Edge>() {
                @Override
                public int compare(Edge o1, Edge o2) {
                    return o1.w - o2.w;
                }
            });
            for (int i = 1; i <= n; i++) {
                p[i] = i;
                size[i] = 1;
            }
            int res = 0;
            for (int i = 0; i < n - 1; i++) {
                int a = find(e[i].a);
                int b = find(e[i].b);
                int w = e[i].w;
                if (a != b) {
                    res += (size[a] * size[b] - 1) * (w + 1);
                    size[b] += size[a];
                    p[a] = b;
                }
            }
            System.out.println(res);
        }
    }

    private static int find(int x) {
        if (p[x] != x) p[x] = find(p[x]);
        return p[x];
    }
}

class Edge{
    int a;
    int b;
    int w;

    public Edge(int a, int b, int w) {
        this.a = a;
        this.b = b;
        this.w = w;
    }
}

在这里插入图片描述

例题:秘密的牛奶运输
【题目描述】
Farmer John 要把他的牛奶运输到各个销售点。运输过程中,可以先把牛奶运输到一些销售点,再由这些销售点分别运输到其他销售点。 运输的总距离越小,运输的成本也就越低。低成本的运输是 Farmer John 所希望的。不过,他并不想让他的竞争对手知道他具体的运输方案,所以他希望采用费用第二小的运输方案而不是最小的。现在请你帮忙找到该运输方案。
【输入】
第一行是两个整数 N,M,表示顶点数和边数;
接下来 M行每行 3 个整数,x,y,z,表示一条路的两端 x,y 和距离 z。
【输出】
仅一行,输出第二小方案。
【输入样例】
4 4
1 2 100
2 4 200
2 3 250
3 4 100
【输出样例】
450
【提示】
数据范围:
对于全部数据,1≤N≤2000,1≤M≤20000,1≤z≤109​​ ,数据可能有重边。
——————————————————————————————————————————————————————

import java.util.Arrays;
import java.util.Comparator;
import java.util.Scanner;

public class Main {
    static int N = 510;
    static int M = 10010;
    static int n;
    static int m;
    static Edge[] edge = new Edge[M];
    static int[] p = new int[N];
    static int[][] dist = new int[N][N];
    static int[] h = new int[N];
    static int[] e = new int[N * 2];
    static int[] w = new int[N * 2];
    static int[] ne = new int[N * 2];
    static int idx;

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        n = sc.nextInt();
        m = sc.nextInt();
        Arrays.fill(h, -1);
        for (int i = 0; i < m; i++) {
            int a = sc.nextInt();
            int b = sc.nextInt();
            int w = sc.nextInt();
            edge[i] = new Edge(a, b, w);
        }
        Arrays.sort(edge, 0, m, new Comparator<Edge>() {
            @Override
            public int compare(Edge o1, Edge o2) {
                return o1.w - o2.w;
            }
        });
        for (int i = 1; i <= n; i++) {
            p[i] = i;
        }
        long sum = 0;
        for (int i = 0; i < m; i++) {
            int a = edge[i].a;
            int b = edge[i].b;
            int w = edge[i].w;
            int pa = find(a);
            int pb = find(b);
            if (pa != pb) {
                p[pa] = pb;
                sum += w;
                add(a, b, w);
                add(b, a, w);
                edge[i].f = true;
            }
        }
        for (int i = 1; i <= n; i++) {
            dfs(i, -1, 0, dist[i]);
        }
        long res = (long) 1e18;
        for (int i = 0; i < m; i++) {
            if (!edge[i].f) {
                int a = edge[i].a;
                int b = edge[i].b;
                int w = edge[i].w;
                if (w > dist[a][b]) {
                    res = Math.min(res, sum + w - dist[a][b]);
                }
            }
        }
        System.out.println(res);
    }

    private static void dfs(int u, int fa, int maxd, int[] d) {
        d[u] = maxd;
        for (int i = h[u]; i != -1; i = ne[i]) {
            int j = e[i];
            if (j != fa) {
                dfs(j, u, Math.max(maxd, w[i]), d);
            }
        }
    }

    private static void add(int a, int b, int c) {
        e[idx] = b;
        w[idx] = c;
        ne[idx] = h[a];
        h[a] = idx++;
    }

    private static int find(int x) {
        if (p[x] != x) p[x] = find(p[x]);
        return p[x];
    }
}

class Edge{
    int a;
    int b;
    int w;
    boolean f = false;

    public Edge(int a, int b, int w) {
        this.a = a;
        this.b = b;
        this.w = w;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值