poj2395 解题报告

Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 13605 Accepted: 5267
Description

The cows have run out of hay, a horrible event that must be remedied immediately. Bessie intends to visit the other farms to survey their hay situation. There are N (2 <= N <= 2,000) farms (numbered 1..N); Bessie starts at Farm 1. She’ll traverse some or all of the M (1 <= M <= 10,000) two-way roads whose length does not exceed 1,000,000,000 that connect the farms. Some farms may be multiply connected with different length roads. All farms are connected one way or another to Farm 1.

Bessie is trying to decide how large a waterskin she will need. She knows that she needs one ounce of water for each unit of length of a road. Since she can get more water at each farm, she’s only concerned about the length of the longest road. Of course, she plans her route between farms such that she minimizes the amount of water she must carry.

Help Bessie know the largest amount of water she will ever have to carry: what is the length of longest road she’ll have to travel between any two farms, presuming she chooses routes that minimize that number? This means, of course, that she might backtrack over a road in order to minimize the length of the longest road she’ll have to traverse.

Input

  • Line 1: Two space-separated integers, N and M.

  • Lines 2..1+M: Line i+1 contains three space-separated integers, A_i, B_i, and L_i, describing a road from A_i to B_i of length L_i.

Output

  • Line 1: A single integer that is the length of the longest road required to be traversed.

Sample Input

3 3
1 2 23
2 3 1000
1 3 43

Sample Output
43

Hint

OUTPUT DETAILS:

In order to reach farm 2, Bessie travels along a road of length 23. To reach farm 3, Bessie travels along a road of length 43. With capacity 43, she can travel along these roads provided that she refills her tank to maximum capacity before she starts down a road.

Source

USACO 2005 March Silver


解题思路:
由于是根据网上的解题分类找到的这一题,所以拿到手时已提前知道这是求MST最大边的问题。
在第一次求解的时候,采用了MatrixUDG+Prim算法,虽然使用题目给的数据通过,但提交之后一直为WA,不得解。
后通过复习union-find算法,并简单的学习了一下kruskal算法,+邻接表,AC,但是时间却达到了2000+ms,羞愧。由于这段代码是先写的kruskal问题再更改成这题的代码,所以在kruskal方法中,有些许无用代码段,但还是将解题代码贴上来。

解题代码
Kruskal+union-find,有关union-find的问题可查看之前的并查集博客。
(注释有时间后补齐)

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


public class Main{
    private static Edge[] edges;
    private static int[] id;
    private static int[] sz;
    private static int count;

    public Main(int N, Edge[] edges) {
        Main.edges = edges;
        count = N;//顶点
        id = new int[N];
        sz = new int[N];
        for (int i = 0; i < N; i++) {
            id[i] = i;
            sz[i] = 1;
        }
    }

    public int find(int p) {
        while (p != id[p]) p = id[p];
        return p;
    }

    public boolean union(int p, int q) {
        int i = find(p);
        int j = find(q);
        if (i == j) {
            return false;
        }
        if (sz[i] < sz[j]) {
            id[i] = j;
            sz[j] += sz[i];
        } else {
            id[j] = i;
            sz[i] += sz[j];
        }
        return true;
    }

    public int kruskal() {
        Arrays.sort(edges);
        int max = -1;
        int elen = 0;
        int sum = 0;
        for (int i = 0; i < edges.length; ++i) {
            if (union(edges[i].getStart(), edges[i].getDest())) {
                elen++;
                max = edges[i].getWeight();
                sum += edges[i].getWeight();
            }
            if (elen == count - 1) {
                System.out.println(max);
                return sum;
            }
        }
        return -1;
    }

    static class Edge implements Comparable<Edge> {
        private int start;
        private int dest;
        private int weight;

        public Edge(int start, int dest, int weight) {
            this.start = start;
            this.dest = dest;
            this.weight = weight;
        }

        public int getStart() {
            return start;
        }

        public int getDest() {
            return dest;
        }

        public int getWeight() {
            return weight;
        }

        @Override
        public int compareTo(Edge o) {
            if (this.weight > o.getWeight()) {
                return 1;
            }
            if (this.getWeight() == o.getWeight()) {
                return 0;
            } else return -1;

        }

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int farmNum = scanner.nextInt();
        int routeNum = scanner.nextInt();
        Edge[] edges = new Edge[routeNum];
        for (int i = 0; i < routeNum; i++) {
            int s = scanner.nextInt() - 1;
            int d = scanner.nextInt() - 1;
            int weight = scanner.nextInt();
            edges[i] = new Edge(s, d, weight);
        }
        new Main(farmNum, edges).kruskal();
    }
}

顺便也将一直WA的prim算法的代码贴上来,如果大家能发现问题,还希望指出。

package poj;

import java.util.Scanner;


/**
 * MST的最大边
 * Created by zzhy on 2016/1/12.
 */

public class proj2395 {
    private static final int INF = Integer.MAX_VALUE / 2;
    private static int[][] matrix;

    private static int prim() {
        int start = 0;
        int num = matrix.length;
        int index = 0;
        int[] weight = new int[num];
        int[] route = new int[num];
        route[index++] = 0;

        //初始化weight
        for (int i = 0; i < num; i++) {
            weight[i] = matrix[start][i];
        }

        //遍历节点
        for (int i = 0; i < num; i++) {
            if (i == start) continue;
            int k = minIndex(weight);
            weight[k] = 0;
            route[index++] = k;

            //更新weight
            for (int j = 0; j < num; j++) {
                if (matrix[k][j] < weight[j]) {
                    weight[j] = matrix[k][j];
                }
            }
        }

        int max = -1;
        int min;
        for (int i = 1; i < index; i++) {
            int n = route[i];
            min = INF;
            for (int j = 0; j < i; j++) {
                int m = route[j];
                if (min > matrix[m][n]) {
                    min = matrix[m][n];
                }
                //MST的最大边
                if (max < min) {
                    max = min;
                }
            }
        }
        return max;
    }

    private static int minIndex(int[] weight) {
        int min = INF;
        int index = -1;
        for (int i = 0; i < weight.length; i++) {
            if (weight[i] != 0 && weight[i] < min) {
                min = weight[i];
                index = i;
            }
        }
        return index;
    }

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int farmNum = scanner.nextInt();
        int roadNum = scanner.nextInt();

        matrix = new int[farmNum][farmNum];
        //初始化matrix
        for (int i = 0; i < farmNum; i++) {
            for (int j = 0; j < farmNum; j++) {
                if (i == j) matrix[i][j] = 0;
                else {
                    matrix[i][j] = INF;
                }
            }
        }

        //读取图
        for (int i = 0; i < roadNum; i++) {
            int m = scanner.nextInt() - 1;
            int n = scanner.nextInt() - 1;
            int l = scanner.nextInt();
            if (matrix[m][n] > l) matrix[m][n] = matrix[n][m] = l;

//            matrix[n][m] = matrix[m][n] = scanner.nextInt();
        }

        //打印图
/*       for (int i = 0 ; i < farmNum ;i++) {
            System.out.println(Arrays.toString(matrix[i]));
        }*//*

        System.out.println(prim());
    }
} */
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
POJ1753题目为"Flip Game",题目给出了一个4x4的棋盘,每个格子有黑色或白色,每次翻转一个格子会同时翻转它上下左右四个格子的颜色,目标是把整个棋盘都变为同一种颜色,求把棋盘变成同种颜色的最小步数。 解题思路: 一般关于棋盘变色的题目,可以考虑使用搜索来解决。对于POJ1753题目,可以使用广度优先搜索(BFS)来解决。 首先,对于每个格子,定义一个状态,0表示当前格子是白色,1表示当前格子是黑色。 然后,我们可以把棋盘抽象成一个长度为16的二进制数,将所有格子的状态按照从左往右,从上往下的顺序排列,就可以用一个16位的二进制数表示整个棋盘的状态。例如,一个棋盘状态为: 0101 1010 0101 1010 则按照从左往右,从上往下的顺序把所有格子的状态连接起来,即可得到该棋盘的状态为"0101101001011010"。 接着,我们可以使用队列来实现广度优先搜索。首先将初始状态加入队列中,然后对于队列中的每一个状态,我们都尝试将棋盘上的每个格子翻转一次,生成一个新状态,将新状态加入队列中。对于每一个新状态,我们也需要记录它是从哪个状态翻转得到的,以便在得到最终状态时能够输出路径。 在搜索过程中,我们需要维护每个状态离初始状态的步数,即将该状态转换为最终状态需要的最小步数。如果我们找到了最终状态,就可以输出答案,即最小步数。 代码实现:

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值