第三章图论(五)

最小生成树

例题:最短网络
在这里插入图片描述
对称矩阵—无向边

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

public class Main {
    static int INF = Integer.MAX_VALUE >> 1;
    static int N = 110;
    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++) {
            for (int j = 1; j <= n; j++) {
                w[i][j] = sc.nextInt();
            }
        }
        System.out.println(prim());
    }

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

例题:局域网(net)
在这里插入图片描述

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

public class Main {
    static int N = 110;
    static int M = 210;
    static int n;
    static int m;
    static int[] p= new int[N];
    static Edge[] e = new Edge[M];

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        n = sc.nextInt();
        m = sc.nextInt();
        for (int i = 1; i <= n; i++) {
            p[i] = i;
        }
        for (int i = 0; i < m; i++) {
            int a = sc.nextInt();
            int b = sc.nextInt();
            int w = sc.nextInt();
            e[i] = new Edge(a, b, w);
        }
        Arrays.sort(e, 0, m, (o1, o2) -> o1.w - o2.w);
        int res = 0;
        for (int i = 0; i < m; i++) {
            int a = find(e[i].a);
            int b = find(e[i].b);
            int w = e[i].w;
            if (a != b) {
                p[a] = b;
            }else {
                res += w;
            }
        }
        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;
    }
}

例题:繁忙的都市(city)
在这里插入图片描述
【输入样例】
4 5
1 2 3
1 4 5
2 4 7
2 3 6
3 4 8
【输出样例】
3 6
————————————————————————————————————————————————————

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

public class Main {
    static int N = 310;
    static int M = 10010;
    static int n;
    static int m;
    static int[] p= new int[N];
    static Edge[] e = new Edge[M];

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        n = sc.nextInt();
        m = sc.nextInt();
        for (int i = 1; i <= n; i++) {
            p[i] = i;
        }
        for (int i = 0; i < m; i++) {
            int a = sc.nextInt();
            int b = sc.nextInt();
            int w = sc.nextInt();
            e[i] = new Edge(a, b, w);
        }
        Arrays.sort(e, 0, m, (o1, o2) -> o1.w - o2.w);
        int res = 0;
        for (int i = 0; i < m; i++) {
            int a = find(e[i].a);
            int b = find(e[i].b);
            int w = e[i].w;
            if (a != b) {
                p[a] = b;
                res = w;
            }
        }
        System.out.println(n - 1 + " " + 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;
    }
}

例题:联络员(liaison)
【题目描述】
Tyvj已经一岁了,网站也由最初的几个用户增加到了上万个用户,随着Tyvj网站的逐步壮大,管理员的数目也越来越多,现在你身为Tyvj管理层的联络员,希望你找到一些通信渠道,使得管理员两两都可以联络(直接或者是间接都可以)。Tyvj是一个公益性的网站,没有过多的利润,所以你要尽可能的使费用少才可以。

目前你已经知道,Tyvj的通信渠道分为两大类,一类是必选通信渠道,无论价格多少,你都需要把所有的都选择上;还有一类是选择性的通信渠道,你可以从中挑选一些作为最终管理员联络的通信渠道。数据保证给出的通行渠道可以让所有的管理员联通。
【输入】
第一行n,m表示Tyvj一共有n个管理员,有m个通信渠道;
第二行到m+1行,每行四个非负整数,p,u,v,w 当p=1时,表示这个通信渠道为必选通信渠道;当p=2时,表示这个通信渠道为选择性通信渠道;u,v,w表示本条信息描述的是u,v管理员之间的通信渠道,u可以收到v的信息,v也可以收到u的信息,w表示费用。
【输出】
最小的通信费用。
【输入样例】
5 6
1 1 2 1
1 2 3 1
1 3 4 1
1 4 1 1
2 2 5 10
2 2 5 5
【输出样例】
9
【提示】
【样例解释】
1-2-3-4-1存在四个必选渠道,形成一个环,互相可以到达。需要让所有管理员联通,需要联通2号和5号管理员,选择费用为5的渠道,所以总的费用为9。
【注意】
U,v之间可能存在多条通信渠道,你的程序应该累加所有u,v之间的必选通行渠道
【数据范围】
对于30%的数据,n≤10,m≤100;
对于50%的数据, n≤200,m≤1000
对于100%的数据,n≤2000,m≤10000
————————————————————————————————————————————————————

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

public class Main {
    static int N = 2010;
    static int M = 10010;
    static int n;
    static int m;
    static int[] p= new int[N];
    static Edge[] e = new Edge[M];

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        n = sc.nextInt();
        m = sc.nextInt();
        for (int i = 1; i <= n; i++) {
            p[i] = i;
        }
        int res = 0, k = 0;
        for (int i = 0; i < m; i++) {
            int t = sc.nextInt();
            int a = sc.nextInt();
            int b = sc.nextInt();
            int w = sc.nextInt();
            if (t == 1) {
                res += w;
                p[find(a)] = find(b);
            }else {
                e[k++] = new Edge(a, b, w);
            }
        }
        Arrays.sort(e, 0, k, (o1, o2) -> o1.w - o2.w);

        for (int i = 0; i < k; i++) {
            int a = find(e[i].a);
            int b = find(e[i].b);
            int w = e[i].w;
            if (a != b) {
                p[a] = b;
                res += w;
            }
        }
        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;
    }
}

例题:连接格点(grid)
在这里插入图片描述
又是多组读入…

import java.util.Scanner;

public class Main {
    static int N = 1010;
    static int M = N * N;
    static int K = 2 * N * N;
    static int n;
    static int m;
    static int k;
    static int[][] ids = new int[N][N];
    static int[] p= new int[M];
    static Edge[] e = new Edge[K];

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        n = sc.nextInt();
        m = sc.nextInt();
        for (int i = 1, t = 1; i <= n; i++) {
            for (int j = 1; j <= m; j++, t++) {
                ids[i][j] = t;
            }
        }
        for (int i = 1; i <= n * m; i++) {
            p[i] = i;
        }
        int x1, y1, x2, y2;
        while (sc.hasNext()) {//读入方式..
            x1 = sc.nextInt();
            y1 = sc.nextInt();
            x2 = sc.nextInt();
            y2 = sc.nextInt();
            int a = ids[x1][y1];
            int b = ids[x2][y2];
            p[find(a)] = find(b);
        }
        get_edges();
        int res = 0;
        for (int i = 0; i < k; i++) {
            int a = find(e[i].a);
            int b = find(e[i].b);
            int w = e[i].w;
            if (a != b) {
                p[a] = b;
                res += w;
            }
        }
        System.out.println(res);
    }

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

    private static void get_edges() {
        int[] dx = {-1, 0, 1, 0};
        int[] dy = {0, 1, 0, -1};
        int[] dw = {1, 2, 1, 2};
        for (int z = 0; z < 2; z++) {
            for (int i = 1; i <= n; i++) {
                for (int j = 1; j <= m; j++) {
                    for (int u = 0; u < 4; u++) {
                        if (u % 2 == z) {
                            int x = i + dx[u];
                            int y = j + dy[u];
                            int w = dw[u];
                            if (x != 0 && x <= n && y != 0 && y <= m) {
                                int a = ids[i][j];
                                int b = ids[x][y];
                                if (a < b) e[k++] = new Edge(a, b, w);
                            }
                        }
                    }
                }
            }
        }
    }
}
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;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值