青云的机房组网方案(简单)-Java

青云现在要将 nnn 个机房连成一个互相连通的网络。工程师小王设计出一个方案:通过在 nnn 个机房之间铺设 n−1n-1n−1 条双向的光纤,将所有的机房连接。可以假设数据在两个机房之间的光纤传输需要 111 单位时间。每个机房 iii 有一个初始值 aia_ia​i​​,当两个机房的初始值之间互质时,我们认为这两个机房之间的传输性能是非常重要的。请帮小王计算出所有数值互质的机房对之间的传输时间之和。

输入格式

第一行输入一个正整数 nnn,第二行输入 nnn 个正整数 a1…ana_1…a_na​1​​…a​n​​,表示 nnn 个机房的初始值。

接下来输入 n−1n-1n−1 行,每行输入两个数 a,ba,ba,b,表示机房 aaa 和机房 bbb 之间有一条双向网络管道。

对于简单版本:n≤500,1≤ai≤501 \leq a_i \leq 501≤a​i​​≤50;;

对于中等版本:n≤10000n \leq 10000n≤10000, 1≤ai≤5001 \leq a_i \leq 5001≤a​i​​≤500;

对于困难版本:n≤100000n \leq 100000n≤100000,ai≤100000a_i \leq 100000a​i​​≤100000。

输出格式

输出一行,表示所有初始值互质的机房对的传输时间和。
样例输入

4
1 2 3 4
1 2
2 3
3 4

样例输出

8

提示信息

对于第一组样例,每一组初始值互质的机房对的传输时间如下:

(1,2:1

(1,3):2

(1,4):3

(2,3):1

(3,4):1

所以,所有初始值互质的机房对的传输时间和为 1+2+3+1+1=8。

import java.util.Scanner;


public class Main {

    private static int n, u;
    private static int inf = 999999999;
    private static int[][] map;
    private static int[][] count;
    private static int sum=0;

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Scanner sc = new Scanner(System.in);
        n = sc.nextInt();
        int[] data = new int[n];
        for (int i = 0; i < data.length; i++) {
            data[i] = sc.nextInt();
        }
        count=new int[n-1][n];
        map = new int[n][n];
        for (int i = 0; i < n; i++) {  
            for (int j = 0; j < n; j++) {  
                map[i][j] = inf;  
            }  
            map[i][i] = 0;  
        } 
        for (int i = 1; i < n; i++) {
            int p1 = sc.nextInt() - 1;
            int p2 = sc.nextInt() - 1;
            map[p1][p2] = 1;
            map[p2][p1] = 1;
        }
        for (int i = 0; i < data.length-1 ; i++) {
                dis(i);
        }
        for (int i = 0; i < data.length-1; i++) {
            if (i+1<data.length) {
                for (int j = i+1; j < data.length; j++) {
                    if(is_prime(data[i], data[j])==1 ){
                        sum+=count[i][j];
                    }
                }
            }
        }
        System.out.println(sum);
    }
    private static void dis(int star) {
        // TODO Auto-generated method stub
        int[] dis = new int[n];
        for (int i = 0; i < n; i++) {
            dis[i] = map[star][i];// 取star号顶点到各个顶点的距离
        }

        // book数组初始化
        int[] book = new int[n];
        book[star] = 1;

        // dijkstra核心算法
        /*
         * 为什么是n-1 呢?
         * 
         * 最短路径肯定是一个不包含回路的 简单路径,回路分为正权回路(回路权值之和为正) 和负权回路(回路权值之和为负)
         * 如果最短路径中包含正权回路,那么去掉这个回路,一定可以得到更短的路径 。 如果路径中包含负权回路,那么肯定没有
         * 最短路径,因为没多走一次负权回路,就可以得到更短的路径。 因此最路径肯定是一个不包含回路的简单路径,即最多包含
         * n-1条路径,所以进行n-1次松弛就可以了
         * 
         */
        for (int i = 0; i < n - 1; i++) {
            int min = inf;
            for (int j = 0; j < n; j++) {
                if (book[j] == 0 && dis[j] < min) {
                    min = dis[j];
                    u = j;
                }
            }
            book[u] = 1;
            for (int v = 0; v < n; v++) {
                if (map[u][v] < inf) {
                    if (dis[v] > dis[u] + map[u][v]) {// dis数组表示的是1号顶点到各个顶点的最短距离,
                        // 1号顶点到v的距离 与通过u顶点中转后
                        // 到v顶点的距离做对比,
                        dis[v] = dis[u] + map[u][v];
                    }
                }
            }
        }
//      for (int i = 0; i < n; i++) {
//          System.out.print(dis[i] + "\t");
//      }
        count[star]=dis;

    }

    private static int is_prime(int a, int b) {
        // TODO Auto-generated method stub
        if (a < b) {
            int tmp = a;
            a = b;
            b = tmp;
        }
        int c;
        while ((c = a % b) != 0) {
            a = b;
            b = c;
        }
        return b;
    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值