All-Pairs Shortest Paths
1. Disjoint Set
Before we talk about more graph algorithms, we shall take a breath and review a basic data structure called Disjoint Set. I provide my solution to the USACO training problem "castle" here in order to evoke your memory about it:
1 import java.io.*; 2 import java.util.*; 3 4 class DisjointSet { 5 private int[] root; // root of each item 6 private int size; // number of items 7 8 public DisjointSet(int size) { 9 if (size<=0) { 10 throw new RuntimeException("Illegal Initial Size"); 11 } else { 12 this.size = size; 13 root = new int[size]; 14 for (int i=0;i<size;i++) { 15 root[i] = -1; 16 } 17 } 18 } 19 public int find(int idx) { 20 // Determine and return root[idx] 21 if (idx<0||idx>=size) { 22 throw new RuntimeException("IndexOutOfBounds on find"); 23 } else { 24 int prev = root[idx]; 25 if (prev<0) { 26 return idx; 27 } else { 28 root[idx] = find(prev); 29 return root[idx]; 30 } 31 } 32 } 33 public void union(int i,int j) { 34 // Merge the set of i and the set of j 35 if (i<0||i>=size||j<0||j>=size) { 36 throw new RuntimeException("IndexOutOfBounds on union"); 37 } else { 38 i = find(i); 39 j = find(j); 40 if (i!=j) { 41 // BEWARE that i and j may be identical 42 if (root[i]<root[j]) { 43 root[i] += root[j]; 44 root[j] = i; 45 } else { 46 root[j] += root[i]; 47 root[i] = j; 48 } 49 } 50 } 51 } 52 public int getSize() { 53 return size; 54 } 55 public int getNum() { 56 int val = 0; 57 for (int i=0;i<size;i++) { 58 if (root[i]<0) { 59 val++; 60 } 61 } 62 return val; 63 } 64 public int getSetSize(int pos) { 65 return -root[find(pos)]; 66 } 67 } 68 69 70 public class castle { 71 public static BufferedReader input; 72 public static PrintWriter output; 73 public static DisjointSet set; 74 public static int wid, len; 75 public static int [][] map; 76 77 public static void removeWall() { 78 int val=0, x=0, y=0; 79 char w = '\0'; 80 for (int j=0;j<len;j++) { 81 for (int i=wid-1;i>=0;i--) { 82 int self = set.find(i*len+j); 83 if (i>0) { 84 int north = set.find((i-1)*len+j); 85 if (self!=north && val<set.getSetSize(self)+set.getSetSize(north)) { 86 val = set.getSetSize(self)+set.getSetSize(north); 87 x = i+1; 88 y = j+1; 89 w = 'N'; 90 } 91 } 92 if (j<len-1) { 93 int east = set.find(i*len+j+1); 94 if (self!=east && val<set.getSetSize(self)+set.getSetSize(east)) { 95 val = set.getSetSize(self)+set.getSetSize(east); 96 x = i+1; 97 y = j+1; 98 w = 'E'; 99 } 100 } 101 } 102 } 103 output.println(val); 104 output.println(x+" "+y+" "+w); 105 } 106 public static void main(String[] args) throws IOException { 107 input = new BufferedReader(new FileReader("castle.in")); 108 StringTokenizer str = new StringTokenizer(input.readLine()); 109 len = Integer.parseInt(str.nextToken()); 110 wid = Integer.parseInt(str.nextToken()); 111 set = new DisjointSet(wid*len); 112 map = new int[wid][len]; 113 int wall; 114 for (int i=0;i<wid;i++) { 115 str = new StringTokenizer(input.readLine()); 116 for (int j=0;j<len;j++) { 117 wall = Integer.parseInt(str.nextToken()); 118 map[i][j] = wall; 119 if ((wall&1)==0){ // West 120 set.union(i*len+j,i*len+j-1); 121 } 122 if ((wall&2)==0) // North 123 set.union(i*len+j,(i-1)*len+j); 124 } 125 } 126 input.close(); 127 output = new PrintWriter(new FileWriter("castle.out")); 128 output.println(set.getNum()); 129 int max = 0; 130 for (int i=0;i<set.getSize();i++) { 131 if (max<set.getSetSize(i)) { 132 max = set.getSetSize(i); 133 } 134 } 135 output.println(max); 136 removeWall(); 137 output.close(); 138 } 139 }
2. Floyd-Warshall Algorithm
In this section, I'll use Floyd-Warshall Algorihtm to determine all-pairs shortest paths and solve the USACO training problem "cowtour":
1 import java.io.*; 2 import java.util.*; 3 import java.text.*; 4 5 class DisjointSet { 6 private int[] root; // root of each item 7 private int size; // number of items 8 9 public DisjointSet(int size) { 10 if (size<=0) { 11 throw new RuntimeException("Illegal Initial Size"); 12 } else { 13 this.size = size; 14 root = new int[size]; 15 for (int i=0;i<size;i++) { 16 root[i] = -1; 17 } 18 } 19 } 20 public int find(int idx) { 21 // Determine and return root[idx] 22 if (idx<0||idx>=size) { 23 throw new RuntimeException("IndexOutOfBounds on find"); 24 } else { 25 int prev = root[idx]; 26 if (prev<0) { 27 return idx; 28 } else { 29 root[idx] = find(prev); 30 return root[idx]; 31 } 32 } 33 } 34 public void union(int i,int j) { 35 // Merge the set of i and the set of j 36 if (i<0||i>=size||j<0||j>=size) { 37 throw new RuntimeException("IndexOutOfBounds on union"); 38 } else { 39 i = find(i); 40 j = find(j); 41 if (i!=j) { 42 // BEWARE that i and j may be identical 43 if (root[i]<root[j]) { 44 root[i] += root[j]; 45 root[j] = i; 46 } else { 47 root[j] += root[i]; 48 root[i] = j; 49 } 50 } 51 } 52 } 53 } 54 55 public class cowtour { 56 public static final int INF = 1000000000; 57 public static Scanner input; 58 public static PrintWriter output; 59 public static int num; 60 public static int [][] point; 61 public static double [][] dist; 62 public static DisjointSet set; 63 64 public static double calDist(int i,int j) { 65 double distSq = Math.pow(point[i][0]-point[j][0],2) 66 + Math.pow(point[i][1]-point[j][1], 2); 67 return Math.sqrt(distSq); 68 } 69 public static void shortDist() { 70 // Floyd-Warshall Algorithm: 71 for (int i=0;i<num;i++) { 72 for (int j=0;j<num;j++) { 73 for (int k=0;k<num;k++) { 74 if (dist[k][j]>dist[k][i]+dist[i][j]) { 75 dist[k][j]=dist[j][k]=dist[k][i]+dist[i][j]; 76 } 77 } 78 } 79 } 80 } 81 public static double calAllDiameter(double [] d) { 82 double val = 0; 83 for (int i=0;i<num;i++) { 84 d[i] = 0; 85 for (int j=0;j<num;j++) { 86 if (set.find(i)==set.find(j) && dist[i][j]>d[i]) { 87 d[i] = dist[i][j]; 88 } 89 } 90 if (d[i]>val) { 91 val = d[i]; 92 } 93 } 94 return val; 95 } 96 public static void solve() { 97 shortDist(); 98 double [] d = new double[num]; 99 double limit = calAllDiameter(d); 100 double val = INF; 101 for (int i=0;i<num;i++) { 102 for (int j=0;j<i;j++) { 103 if (set.find(i)!=set.find(j)) { 104 double max = d[i]+calDist(i,j)+d[j]; 105 if (limit>max) { 106 max = limit; 107 } 108 if (val>max) { 109 val = max; 110 } 111 } 112 } 113 } 114 DecimalFormat df = new DecimalFormat(".000000"); 115 output.println(df.format(val)); 116 } 117 public static void main(String[] args) throws IOException { 118 input = new Scanner(new FileReader("cowtour.in")); 119 num = input.nextInt(); 120 point = new int [num][2]; 121 dist = new double[num][num]; 122 for (int i=0;i<num;i++) { 123 point[i][0] = input.nextInt(); 124 point[i][1] = input.nextInt(); 125 } 126 set = new DisjointSet(num); 127 for (int i=0;i<num;i++) { 128 String line = input.next(); 129 for (int j=0;j<num;j++) { 130 if (line.charAt(j)=='1') { 131 dist[i][j]=dist[j][i]=calDist(i,j); 132 set.union(i, j); 133 } else { 134 dist[i][j]=dist[j][i]=INF; 135 } 136 } 137 dist[i][i] = 0; 138 } 139 input.close(); 140 output = new PrintWriter(new FileWriter("cowtour.out")); 141 solve(); 142 output.close(); 143 } 144 }