poj-1125

31 篇文章 0 订阅
// 3072K    250MS    Java
import java.util.Arrays;
import java.util.Comparator;
import java.util.Scanner;

public class Main{
    private static final int INF = 99999;
    private static final int UNREACH = -1;
    private static final int MAX = 100;
    private static int sStokerNum;

    public int[][] stokerInfo;

    public void reset() {
        sStokerNum = 0;
        for (int i = 0; i < MAX; i++) {
            for (int j = 0; j < MAX; j++) {
                if (i == j) {
                    stokerInfo[i][j] = 0;
                } else {
                    stokerInfo[i][j] = INF;
                }
            }
        }
    }

    public void solve() {
        for (int k = 1; k <= sStokerNum; k++) {
            for (int i = 0; i < sStokerNum; i++) {
                for (int j = 0; j < sStokerNum; j++) {
                    int d1 = stokerInfo[i][j];
                    int d2 = stokerInfo[i][k-1] + stokerInfo[k-1][j];
                    stokerInfo[i][j] = d1 < d2 ? d1 : d2;
                }
            }
        }

        // for (int i = 0; i < sStokerNum; i++) {
        //     for (int j = 0; j < sStokerNum; j++) {
        //         System.out.print(stokerInfo[i][j] + " ");
        //     }
        //     System.out.println("");
        // }

        int bestStokerId = -1;
        int shortestTime = INF;
        for (int i = 0; i < sStokerNum; i++) { // check ith stoker
            int longestTransTime = -1;
            for (int j = 0; j < sStokerNum; j++) {
                longestTransTime = stokerInfo[i][j] > longestTransTime ? stokerInfo[i][j] : longestTransTime;
            }
            // System.out.println(i + " " + longestTransTime);
            if (longestTransTime < shortestTime) { // update
                bestStokerId = i;
                shortestTime = longestTransTime;
            }
            // bestStokerId = longestTransTime < shortestTime ? i : bestStokerId;
        }

        if (bestStokerId == -1) {
            System.out.println("disjoint");
        } else {
            System.out.println((bestStokerId + 1) + " " + shortestTime);
        }

        reset();
    }

    public Main() {
        stokerInfo = new int[MAX][MAX];
        reset();
    }

    public static void main(String args[]) {
        Main solver = new Main();
        Scanner scanner = new Scanner(System.in);
        while(true) {
            int stokerNum = scanner.nextInt();
            if (stokerNum == 0) {
                return;
            }
            sStokerNum = stokerNum;
            for (int i = 0; i < stokerNum; i++) {
                int contactNum = scanner.nextInt();
                for (int j = 0; j < contactNum; j++) {
                    int contactId = scanner.nextInt();
                    int time = scanner.nextInt();
                    solver.stokerInfo[i][contactId-1] = time;
                }
            }
            solver.solve();            
        }
    }

}


一道基本的多点对之间最短路径题,用的是标准的Floyd-Warshall算法。

题目转化很简单,一读就直到想要的是什么,不过以前没搞过FW算法,花了些时间学习了下。

算导对FW讲的虽然短,但是很好,揭露了其本质是DP算法.

假设D(i, j ,k) 表示从i到j的最短路径,并且该最短路径包含的中间点不会超过k(即k之后的点都不会被涉及到,这里的k值得是对图的点的编号,谁前谁后无所谓,但必须编号来体现出前后差异)。

那么D(i, j, k+1) 的递推就可以表示了:

case1 如果第k+1个点包含在了D(i, j, k+1)的最短路径中,那么D(i,j, k+1) = D(i, k+1, k) + D(k+1, j, k)

case2 如果第k+1个点没有包含在D(i, j, k+1)的最短路径中, 那么第k+1点的加入相当于没有任何影响,因此D(i,j, k+1) = D(i, j, k).

至于是case1还是case2, 就是通过比较两种情况下哪个路径最短来决定的。

这样动态规划的递推式就是:

D(i, j, k+1) = MIN(D(i, k+1, k) + D(k+1, j, k),  D(i, j, k)) (会有 k+1 ==i 或者 k+1==j的情况,这种情况, D(i, k+1, k) + D(k+1, j, k) = D(i, j, k))

有3个变化量,因此动态规划递归求解的方式是三重循环:

看一下倚赖关系:  k+1 依赖于k, 因此 k的循环要从小到大,并且k从1开始,k=0表示最短路径间没有任何中间点,就是两个点之间之否有直接连接,这等于是初始状态,

这也表示k是DP中的主变量,要以k作为第一重循环.

i 虽然依赖于 k+1 (k+1可能比i大,也可能小), 但要注意,其实第k+1轮倚赖的是第k论结果,因此实际上,i从大到小或相反是不影响的,

j 同i,

i,j作为第2,3轮循环,前后无所谓。

传统的DP在这时候要开三维矩阵来保存中间值以进行DP,但是这种情况完全可以把3维压缩成2维,

第k+1的轮的结果只依赖于第k轮,之前的结果不会影响,因此完全可以在求第k+1论的结果的过程中,一边求,一边覆盖相应的的第k轮的中间结果(要注意保证不能覆盖还没有被使用的第k轮结果),这样只用一个二维矩阵就可以求了。

最后对于本题来说,就是一次查询每一个stoker对其他人是否全部可达,如果可达,求出最长的路径,如果不可达,则不予考虑,

如果下一个stoker的全部可达,且最长路径比之前的stoker中的最短的最长路径(有点绕)还要短,则更新最短的最长路径和stokerid。

最后如果没有stoker能全部可达其他人,则disjoint,否则输出stokerId和其最长的路径(就是从他开始传播到最后也是最晚一个stoker的时间)

还要注意初始化时,要给邻接矩阵合适的值,D(i,i) = 0(自己到自己当然是0)不可达(也是所有的初始状态)给一个极大值INF(自己定9999999),其他的按照input的值来。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值