• 《算法》第四章部分程序 part 19


    ▶ 书中第四章部分程序,包括在加上自己补充的代码,有边权有向图的邻接矩阵,FloydWarshall 算法可能含负环的有边权有向图任意两点之间的最短路径

    ● 有边权有向图的邻接矩阵

      1 package package01;
      2 
      3 import java.util.Iterator;
      4 import java.util.NoSuchElementException;
      5 import edu.princeton.cs.algs4.StdOut;
      6 import edu.princeton.cs.algs4.StdRandom;
      7 import edu.princeton.cs.algs4.DirectedEdge;
      8 
      9 public class class01
     10 {
     11     private static final String NEWLINE = System.getProperty("line.separator");
     12 
     13     private final int V;
     14     private int E;
     15     private DirectedEdge[][] adj;
     16 
     17     public class01(int inputV)
     18     {
     19         if (inputV < 0)
     20             throw new IllegalArgumentException("
    <Constructor> V < 0.
    ");
     21         V = inputV;
     22         E = 0;
     23         adj = new DirectedEdge[V][V];
     24     }
     25 
     26     public class01(int inputV, int inputE)
     27     {
     28         this(inputV);
     29         if (inputE < 0 || inputE > V*V)
     30             throw new IllegalArgumentException("
    <Constructor> E < 0 || E > V*V.
    ");
     31 
     32         for (E = 0; E != inputE;)
     33         {
     34             int v = StdRandom.uniform(V), w = StdRandom.uniform(V);
     35             double weight = Math.round(100 * StdRandom.uniform()) / 100.0;
     36             addEdge(new DirectedEdge(v, w, weight));
     37         }
     38     }
     39 
     40     public int V()
     41     {
     42         return V;
     43     }
     44 
     45     public int E()
     46     {
     47         return E;
     48     }
     49 
     50     public void addEdge(DirectedEdge e)
     51     {
     52         int v = e.from();
     53         int w = e.to();
     54         if (adj[v][w] == null)
     55         {
     56             E++;
     57             adj[v][w] = e;
     58         }
     59     }
     60 
     61     public Iterable<DirectedEdge> adj(int v)
     62     {
     63         return new AdjIterator(v);
     64     }
     65 
     66     private class AdjIterator implements Iterator<DirectedEdge>, Iterable<DirectedEdge>
     67     {
     68         private int v;
     69         private int w = 0;
     70 
     71         public AdjIterator(int inputV)
     72         {
     73             v = inputV;
     74         }
     75 
     76         public Iterator<DirectedEdge> iterator()
     77         {
     78             return this;
     79         }
     80 
     81         public boolean hasNext()    // 同一行里还有元素(还有以该顶点为起点的边)
     82         {
     83             for (; w < V; w++)
     84             {
     85                 if (adj[v][w] != null)
     86                     return true;
     87 
     88             }
     89             return false;
     90         }
     91 
     92         public DirectedEdge next()
     93         {
     94             if (!hasNext())
     95                 throw new NoSuchElementException();
     96             return adj[v][w++];
     97         }
     98 
     99         public void remove()
    100         {
    101             throw new UnsupportedOperationException();
    102         }
    103     }
    104 
    105     public String toString()
    106     {
    107         StringBuilder s = new StringBuilder();
    108         s.append(V + " " + E + NEWLINE);
    109         for (int v = 0; v < V; v++)
    110         {
    111             s.append(v + ": ");
    112             for (DirectedEdge e : adj(v))
    113                 s.append(e + "  ");
    114             s.append(NEWLINE);
    115         }
    116         return s.toString();
    117     }
    118 
    119     public static void main(String[] args)
    120     {
    121         int V = Integer.parseInt(args[0]);
    122         int E = Integer.parseInt(args[1]);
    123         class01 G = new class01(V, E);
    124         StdOut.println(G);
    125     }
    126 }

    ● FloydWarshall 算法可能含负环的有边权有向图任意两点之间的最短路径

      1 package package01;
      2 
      3 import edu.princeton.cs.algs4.StdOut;
      4 import edu.princeton.cs.algs4.StdRandom;
      5 import edu.princeton.cs.algs4.DirectedEdge;
      6 import edu.princeton.cs.algs4.EdgeWeightedDigraph;
      7 import edu.princeton.cs.algs4.EdgeWeightedDirectedCycle;
      8 import edu.princeton.cs.algs4.Stack;
      9 import edu.princeton.cs.algs4.AdjMatrixEdgeWeightedDigraph;
     10 
     11 public class class01
     12 {
     13     private boolean hasNegativeCycle;  // 是否有负环
     14     private double[][] distTo;         // 从 v 到 w 的最短路径记作 distTo[v][w]
     15     private DirectedEdge[][] edgeTo;   // 从 v 到 w 的最短路径的最后一条边记作 edgeTo[v][w]
     16 
     17     public class01(AdjMatrixEdgeWeightedDigraph G)
     18     {
     19         int V = G.V();
     20         distTo = new double[V][V];
     21         edgeTo = new DirectedEdge[V][V];
     22         for (int v = 0; v < V; v++)     // 邻接表元素初始化为正无穷
     23         {
     24             for (int w = 0; w < V; w++)
     25                 distTo[v][w] = Double.POSITIVE_INFINITY;
     26         }
     27         for (int v = 0; v < G.V(); v++)
     28         {
     29             for (DirectedEdge e : G.adj(v))     // 添加以 v 为起点的各条边
     30             {
     31                 distTo[e.from()][e.to()] = e.weight();
     32                 edgeTo[e.from()][e.to()] = e;
     33             }
     34             if (distTo[v][v] >= 0.0)            // 自环归零
     35             {
     36                 distTo[v][v] = 0.0;
     37                 edgeTo[v][v] = null;
     38             }
     39         }
     40         for (int i = 0; i < V; i++)             // 循环 V 次
     41         {
     42             for (int v = 0; v < V; v++)         // 用 0 ~ i 作为中间顶点,尝试将其引入
     43             {
     44                 if (edgeTo[v][i] == null)       // v 不可达 i,跳过
     45                     continue;
     46                 for (int w = 0; w < V; w++)
     47                 {
     48                     if (distTo[v][w] > distTo[v][i] + distTo[i][w]) // 引入顶点 i 使得 v 到 w 的距离缩短
     49                     {
     50                         distTo[v][w] = distTo[v][i] + distTo[i][w]; // 正式引入顶点 i
     51                         edgeTo[v][w] = edgeTo[i][w];
     52                     }
     53                 }
     54                 if (distTo[v][v] < 0.0)         // 检测负环,条件是某顶点到自身的最短路径小于 0
     55                 {
     56                     hasNegativeCycle = true;
     57                     return;
     58                 }
     59             }
     60         }
     61     }
     62 
     63     public boolean hasNegativeCycle()
     64     {
     65         return hasNegativeCycle;
     66     }
     67 
     68     public Iterable<DirectedEdge> negativeCycle()
     69     {
     70         for (int v = 0; v < distTo.length; v++)
     71         {
     72             if (distTo[v][v] < 0.0)
     73             {
     74                 int V = edgeTo.length;
     75                 EdgeWeightedDigraph spt = new EdgeWeightedDigraph(V);
     76                 for (int w = 0; w < V; w++)         // 把与 v 有关的边加入一个含边权有向图,用类 EdgeWeightedDirectedCycle 寻找环
     77                 {
     78                     if (edgeTo[v][w] != null)       // 实际上所有从 v 延伸出去的最短路径的边都加上了
     79                         spt.addEdge(edgeTo[v][w]);
     80                 }
     81                 EdgeWeightedDirectedCycle finder = new EdgeWeightedDirectedCycle(spt);
     82                 return finder.cycle();
     83             }
     84         }
     85         return null;
     86     }
     87 
     88     public boolean hasPath(int s, int t)
     89     {
     90 
     91         return distTo[s][t] < Double.POSITIVE_INFINITY;
     92     }
     93 
     94     public double dist(int s, int t)
     95     {
     96         if (hasNegativeCycle())
     97             throw new UnsupportedOperationException("
    <dist> Negative cost cycle exists.
    ");
     98         return distTo[s][t];
     99     }
    100 
    101     public Iterable<DirectedEdge> path(int s, int t)
    102     {
    103         if (hasNegativeCycle())
    104             throw new UnsupportedOperationException("
    <Iterable> Negative cost cycle exists.
    ");
    105         if (!hasPath(s, t))
    106             return null;
    107         Stack<DirectedEdge> path = new Stack<DirectedEdge>();
    108         for (DirectedEdge e = edgeTo[s][t]; e != null; e = edgeTo[s][e.from()])
    109             path.push(e);
    110         return path;
    111     }
    112 
    113     public static void main(String[] args)
    114     {
    115         int V = Integer.parseInt(args[0]);
    116         int E = Integer.parseInt(args[1]);
    117         AdjMatrixEdgeWeightedDigraph G = new AdjMatrixEdgeWeightedDigraph(V);
    118         for (int i = 0; i < E; i++)
    119         {
    120             int v = StdRandom.uniform(V);
    121             int w = StdRandom.uniform(V);
    122             double weight = Math.round(100 * (StdRandom.uniform() - 0.15)) / 100.0;
    123             if (v == w) G.addEdge(new DirectedEdge(v, w, Math.abs(weight)));
    124             else G.addEdge(new DirectedEdge(v, w, weight));
    125         }
    126 
    127         StdOut.println(G);
    128         class01 spt = new class01(G);
    129         StdOut.printf("  ");
    130         for (int v = 0; v < G.V(); v++)
    131             StdOut.printf("%6d ", v);
    132         StdOut.println();
    133         for (int v = 0; v < G.V(); v++)
    134         {
    135             StdOut.printf("%3d: ", v);
    136             for (int w = 0; w < G.V(); w++)
    137             {
    138                 if (spt.hasPath(v, w))
    139                     StdOut.printf("%6.2f ", spt.dist(v, w));
    140                 else
    141                     StdOut.printf("  Inf ");    // 存在负环的路径长度显示为负无穷
    142             }
    143             StdOut.println();
    144         }
    145         if (spt.hasNegativeCycle())             // 有负环单独显示,否则正常显示各条最短路径
    146         {
    147             StdOut.println("Negative cost cycle:");
    148             for (DirectedEdge e : spt.negativeCycle())
    149                 StdOut.println(e);
    150             StdOut.println();
    151         }
    152         else
    153         {
    154             for (int v = 0; v < G.V(); v++)
    155             {
    156                 for (int w = 0; w < G.V(); w++)
    157                 {
    158                     if (spt.hasPath(v, w)) {
    159                         StdOut.printf("%d to %d (%5.2f)  ", v, w, spt.dist(v, w));
    160                         for (DirectedEdge e : spt.path(v, w))
    161                             StdOut.print(e + "  ");
    162                         StdOut.println();
    163                     }
    164                     else
    165                         StdOut.printf("%d to %d no path
    ", v, w);
    166                 }
    167             }
    168         }
    169     }
    170 }
  • 相关阅读:
    registration system(map+思维)
    Codeforces 158B:Taxi(贪心)
    牛客小白月赛24 B-组队(二分)
    CF58C Trees(逆向思维)
    lower_bound和upper_bound学习笔记
    POJ--2689Prime Distance(区间素数筛)
    Codeforces Round #635 (Div. 2)
    navicat premium安装,使用
    Oracel 之PL/SQL Developer使用
    PLSQL,sql语句中带有中文的查询条件查询不到数据
  • 原文地址:https://www.cnblogs.com/cuancuancuanhao/p/9836349.html
Copyright © 2020-2023  润新知