SAP.java

package cn.denghanxi.assignment.s42;

import edu.princeton.cs.algs4.BreadthFirstDirectedPaths;
import edu.princeton.cs.algs4.Digraph;

/**
 * shortest ancestral path
 * 两个顶点v,w。他们最近的共同祖先节点
 *
 * 目前解法,对两个source进行完整的BFS,从头遍历,找到都连接source并且距离之和最小的节点
 *
 * 优化:不用完整BFS,依次对两个source BFS ,找到共同的就停止?
 */
public class SAP {

    Digraph digraph;

    public SAP(Digraph digraph) {
        if (digraph == null) throw new IllegalArgumentException("constructor null");
        this.digraph = digraph;
    }

    public int length(int v, int w) {
        if (v < 0 || w < 0 || v >= digraph.V() || w > digraph.V()) throw new IllegalArgumentException("outOfRange");
        BreadthFirstDirectedPaths pathsToV = new BreadthFirstDirectedPaths(digraph, v);
        BreadthFirstDirectedPaths pathsToW = new BreadthFirstDirectedPaths(digraph, w);
        int shortest = Integer.MAX_VALUE;
        for (int i = 0; i < digraph.V(); i++) {
            if (pathsToV.hasPathTo(i) && pathsToW.hasPathTo(i))
                if ((pathsToV.distTo(i) + pathsToW.distTo(i) < shortest))
                    shortest = pathsToV.distTo(i) + pathsToW.distTo(i);
        }
        if (shortest != Integer.MAX_VALUE) {
            return shortest;
        } else {
            return -1;
        }
    }

    public int ancestor(int v, int w) {
        if (v < 0 || w < 0 || v >= digraph.V() || w > digraph.V()) throw new IllegalArgumentException("outOfRange");
        BreadthFirstDirectedPaths pathsToV = new BreadthFirstDirectedPaths(digraph, v);
        BreadthFirstDirectedPaths pathsToW = new BreadthFirstDirectedPaths(digraph, w);
        int shortest = Integer.MAX_VALUE;
        int ancestor = -1;
        for (int i = 0; i < digraph.V(); i++) {
            if (pathsToV.hasPathTo(i) && pathsToW.hasPathTo(i))
                if ((pathsToV.distTo(i) + pathsToW.distTo(i) < shortest)) {
                    shortest = pathsToV.distTo(i) + pathsToW.distTo(i);
                    ancestor = i;
                }
        }
        return ancestor;
    }

    public int length(Iterable<Integer> v, Iterable<Integer> w) {
        for (int i : v) {
            if (i < 0 || i > digraph.V()) throw new IllegalArgumentException("outOfRange");
        }
        for (int i : w) {
            if (i < 0 || i > digraph.V()) throw new IllegalArgumentException("outOfRange");
        }
        BreadthFirstDirectedPaths pathsToV = new BreadthFirstDirectedPaths(digraph, v);
        BreadthFirstDirectedPaths pathsToW = new BreadthFirstDirectedPaths(digraph, w);
        int shortest = Integer.MAX_VALUE;
        for (int i = 0; i < digraph.V(); i++) {
            if (pathsToV.hasPathTo(i) && pathsToW.hasPathTo(i))
                if ((pathsToV.distTo(i) + pathsToW.distTo(i) < shortest))
                    shortest = pathsToV.distTo(i) + pathsToW.distTo(i);
        }
        if (shortest != Integer.MAX_VALUE) {
            return shortest;
        } else {
            return -1;
        }
    }

    public int ancestor(Iterable<Integer> v, Iterable<Integer> w) {
        for (int i : v) {
            if (i < 0 || i > digraph.V()) throw new IllegalArgumentException("outOfRange");
        }
        for (int i : w) {
            if (i < 0 || i > digraph.V()) throw new IllegalArgumentException("outOfRange");
        }
        BreadthFirstDirectedPaths pathsToV = new BreadthFirstDirectedPaths(digraph, v);
        BreadthFirstDirectedPaths pathsToW = new BreadthFirstDirectedPaths(digraph, w);
        int shortest = Integer.MAX_VALUE;
        int ancestor = -1;
        for (int i = 0; i < digraph.V(); i++) {
            if (pathsToV.hasPathTo(i) && pathsToW.hasPathTo(i))
                if ((pathsToV.distTo(i) + pathsToW.distTo(i) < shortest)) {
                    shortest = pathsToV.distTo(i) + pathsToW.distTo(i);
                    ancestor = i;
                }
        }
        return ancestor;
    }

    public static void main(String[] args) {

    }

}