Warning
This page is located in archive.

MST and Dijkstra

import java.util.*;
 
public class Solvers {
 
 
// ----------------------------------------------------------------------------
//            D I J K S T R A   N^2                                      
// ----------------------------------------------------------------------------
 
static void dijkstraNsquared(Graph g, int start,  final int [] dist, int [] pred ) {
  int INF = Integer.MAX_VALUE;
  int currnode = start, currdist, neigh;
  boolean [] closed = new boolean [g.N];
 
  for(int i = 0; i < g.N; i++) pred[i] = i;
  Arrays.fill(dist, INF);
  Arrays.fill(closed, false);
  dist[start] = 0;
 
  for( int i = 0; i < g.N; i++ ){
    // find the closest node
    currdist = INF;
    for( int j = 0; j < g.N; j++)
      if( !closed[j] && dist[j] < currdist ){
        currdist = dist[j];
        currnode = j;
      }
 
    // expand the closest node and close it
    for( int j = 0; j < g.dg[currnode]; j++ ){
      neigh = g.edge[currnode][j];
      if( !closed[neigh] && ( dist[neigh] > dist[currnode] + g.w[currnode][j]) ) {
        dist[neigh] = dist[currnode] + g.w[currnode][j];
        pred[neigh] = currnode;
      }
     closed[currnode] = true;
    }
  } // for N steps
}
 
// ----------------------------------------------------------------------------
//            D I J K S T R A   E * log(N)                                     
// ----------------------------------------------------------------------------
 
public static void dijkstraElogN(Graph g, int start, final int [] dist, int [] pred ) {
  int currnode = start, currdist, neigh;
  int INF = Integer.MAX_VALUE;
  boolean [] closed = new boolean[g.N];
 
  PriorityQueue <Integer> pq
    = new PriorityQueue<Integer> (g.N,
          new Comparator<Integer>() {
            @Override
            public int compare(Integer n1, Integer n2) {
              if( dist[n1] < dist[n2] ) return -1;
              if( dist[n1] > dist[n2] ) return 1;
              return 0;
            }
          }
      );
 
  pq.add(start);
  for(int i = 0; i < g.N; i++) pred[i] = i;
  Arrays.fill(dist, INF);
  Arrays.fill(closed, false);
  dist[start] = 0;
 
  for(int i = 0; i < g.N; i++) {
    // current node is to be the nearest one, skip the closed nodes
    while( closed[currnode = pq.poll()] == true );
    // and expand current node
    for( int j = 0; j < g.dg[currnode]; j++ ){
      neigh = g.edge[currnode][j];
      if( !closed[neigh] && ( dist[neigh] > dist[currnode] + g.w[currnode][j]) ) {
        dist[neigh] = dist[currnode] + g.w[currnode][j];
        pred[neigh] = currnode;
        pq.add(neigh);
      }
     closed[currnode] = true;
    }
  }
}
 
// ----------------------------------------------------------------------------
//            M S T   P R I M    N^2                                      
// ----------------------------------------------------------------------------
 
 
static void MST_Nsquared(Graph g, int start,  final int [] dist, int [] pred ) {
  int INF = Integer.MAX_VALUE;
  int currnode = start, currdist, neigh;
  boolean [] closed = new boolean [g.N];
 
  for(int i = 0; i < g.N; i++) pred[i] = i;
  Arrays.fill(dist, INF);
  Arrays.fill(closed, false);
  dist[start] = 0;
 
  for( int i = 0; i < g.N; i++ ){
    // find the closest node
    currdist = INF;
    for( int j = 0; j < g.N; j++)
      if( !closed[j] && dist[j] < currdist ){
        currdist = dist[j];
        currnode = j;
      }
 
    // expand the closest node and close it
    for( int j = 0; j < g.dg[currnode]; j++ ){
      neigh = g.edge[currnode][j];
      if( !closed[neigh] && ( dist[neigh] > g.w[currnode][j]) ) {
        dist[neigh] = g.w[currnode][j];
        pred[neigh] = currnode;
      }
     closed[currnode] = true;
    }
  } // for N steps
}
 
 
// ----------------------------------------------------------------------------
//            M S T   P R I M    E * log(N)                                       
// ----------------------------------------------------------------------------
 
 
public static void MST_ElogN(Graph g, int start, final int [] dist, int [] pred ) {
  int currnode = start, currdist, neigh;
  int INF = Integer.MAX_VALUE;
  boolean [] closed = new boolean[g.N];
 
  PriorityQueue <Integer> pq
    = new PriorityQueue<Integer> (g.N,
          new Comparator<Integer>() {
            @Override
            public int compare(Integer n1, Integer n2) {
              if( dist[n1] < dist[n2] ) return -1;
              if( dist[n1] > dist[n2] ) return 1;
              return 0;
            }
          }
      );
 
  pq.add(start);
  for(int i = 0; i < g.N; i++) pred[i] = i;
  Arrays.fill(dist, INF);
  Arrays.fill(closed, false);
  dist[start] = 0;
 
  for(int i = 0; i < g.N; i++) {
    // take the closest node
    while( closed[currnode = pq.poll()] == true );
    // and expand it
    for( int j = 0; j < g.dg[currnode]; j++ ){
      neigh = g.edge[currnode][j];
      if( !closed[neigh] && ( dist[neigh] > g.w[currnode][j]) ) {
        dist[neigh] = g.w[currnode][j];
        pred[neigh] = currnode;
        pq.add(neigh);
      }
     closed[currnode] = true;
    }
  }
}
 
// ----------------------------------------------------------------------------
//            M S T   K R U S K A L    E * alpha(N)                                       
// ----------------------------------------------------------------------------
 
 
public static void MST_Kruskal(Graph g, int [] edgesMST ) {
 
  // store edges in one arr and sort them
  int [] edges = new int[g.M*3];
  int k = 0;
  for( int i = 0; i < g.N; i++ )
    for( int j = 0; j < g.dg[i]; j++ ) {
      if( i <  g.edge[i][j] ) {
        edges[k++] = g.w[i][j];
        edges[k++] = i;
        edges[k++] = g.edge[i][j];
      }
    }
   qSort3( edges, 0, edges.length-3 );
 
   // construct the MST with UF
   UF_init( g.N );
   int edgesCount = 0, set1, set2;
   k = 0;
   while( edgesCount < g.N-1 ){
     set1 = UF_find(edges[k+1]); set2 = UF_find(edges[k+2]);
     if( set1 != set2 ) {  // found an edge of MST
       UF_union( set1, set2 );
       edgesCount++;
       edgesMST[edgesCount*2-2] = edges[k+1]; 
       edgesMST[edgesCount*2-1] = edges[k+2] ;
     }
     k += 3;
   }
}
 
 
// ----------------------------------------------------------------------------
//                   U N I O N  -  F I N D   
//      (also known as  "Disjoint-set data structure")
//        with path compression and  union by rank                                       
// ----------------------------------------------------------------------------
 
static int [] boss;
static int [] rank;
 
static void UF_init( int n ) {
	boss = new int [n];
	rank = new int [n];
  UF_reset();
}
 
static void UF_reset() {
  for( int i = 0; i < boss.length; i++ ) {
    boss[i] = i;  // fast copy from superboss;
    rank[i] = 0;
  }
}
 
 
static void UF_union( int a, int b ) {
  //System.out.printf(" unioning %d %d \n", a, b);
  if( rank[b] > rank[a] ) 
    boss[a] = b;
  else {
    boss[b] = a;
		if( rank[b] == rank[a] ) 
			rank[a]++;
  }
}
 
static int UF_find(int a) {
	return ( boss[a] == a ?  a  : ( boss[a] = UF_find( boss[a] ) ) );
}
 
/*
static int UF_find(int a) {  // an equivalent to UF_find one-liner
  int parent = boss[a];
  if( parent != a )
    boss[a] = UF_find(parent); 
  return boss[a];
}
*/
 
static void listSet(int a) {  // for debug purposes only
  int finda = UF_find(a);
  for(int i = 0; i < boss.length; i++)
    if(UF_find(i) == finda)
      System.out.printf("%d ", i);
  System.out.printf("\n");
}
 
 
 
// ----------------------------------------------------------------------------
//              U T I L I T I E S
// ----------------------------------------------------------------------------
 
 
static void list (int [] a) {
  for( int x : a )
    System.out.printf("%2d ", x);
  System.out.printf("\n");
}
 
static void qSort(double a[], int low, int high) {
  int iL = low, iR = high;
  double pivot = a[low];
  double aux;
  do {
    while (a[iL] < pivot) iL++;
    while (a[iR] > pivot) iR--;
    if (iL < iR) {
      //swap(a,iL, iR);
      aux = a[iL]; a[iL] = a[iR]; a[iR] = aux;
       iL++; iR--;
    }
    else
      if (iL == iR) { iL++; iR--;}
 
  } while( iL <= iR);
 
  if (low < iR)  qSort(a, low, iR);
  if (iL < high) qSort(a, iL, high);
}
 
 
// always points to i%3=0 elem which stores the key
static void qSort3(int a[], int low, int high) {
  int iL = low, iR = high;
  int pivot = a[low];
  int aux;
  do {
    while (a[iL] < pivot) iL+=3;
    while (a[iR] > pivot) iR-=3;
    if (iL < iR) {
      //swap(a,iL, iR);
      for(int k = 0; k < 3; k++ )
      { aux = a[iL+k]; a[iL+k] = a[iR+k]; a[iR+k] = aux; }
      iL+=3; iR-=3;
    }
    else
      if (iL == iR) { iL+=3; iR-=3;}
 
  } while( iL <= iR);
 
  if (low < iR)  qSort3(a, low, iR);
  if (iL < high) qSort3(a, iL, high);
}
 
// ----------------------------------------------------------------------------
//              M A I N 
// ----------------------------------------------------------------------------
  public static void main( String[] args ) {
 
  }
 
}

Weighted graph manipulation

import java.util.*;
import java.io.*;
 
 
public class Graph {
 
// ----------------------------------------------------------------------------
//                           M  A  I  N                                      
// ----------------------------------------------------------------------------
 
 
public static void main( String[] args ) {
  long t1, t2;
 
  // simple example
  Graph g = Graph.randomConnectedGraph(8, 12, 1, 10, 40112121 );
  g.setRandWeights(1, 15, 3488782 );
  g.print();
 
  t1 = System.currentTimeMillis();
  //Solvers.dijkstraNsquared(g, 0, g.dist, g.pred);
  //listEdgePred( g.pred );
 
  //Solvers.dijkstraElogN(g, 0, g.dist, g.pred);
  //listEdgePred( g.pred );
 
  //Solvers.MST_Nsquared(g, 2, g.dist, g.pred);
  //listEdgePred( g.pred );
 
  //Solvers.MST_ElogN(g, 2, g.dist, g.pred);
  //listEdgePred( g.pred );
 
  int [] edgesMST = new int[2*g.N-2];
  Solvers.MST_Kruskal(g, edgesMST);
  listEdgeArr( edgesMST );
 
   t2 = System.currentTimeMillis();
  System.out.printf("time %d\n", t2-t1);
 
}
 
// ------------------------- G R A P H   I T S E L F -------------------------- 
 
int N, M;       // # of nodes and edges
int [][] edge;  // graph itself, linked lists representation
int [][] w;     // edge weights
int [] dg;      // node degrees
int [] dist;    // node distances 
int [] pred;    // node predecessors in path/search 
 
 
// ----------------------------------------------------------------------------
//                           E S S E N T I A L S
// ----------------------------------------------------------------------------
 
 
// ------------------------- C O N S T R U C T O R ----------------------------  
// creates a graph with n nodes and no edges (so called empty graph) 
 
public Graph ( int n ) {
  N = n; M = 0;
  edge = new int [N][2]; 
  w = new int [N][2];
  dg = new int [N];
  dist = new int [N];
  pred = new int [N];
}
 
// ------------------------- A D D   E D G E  ---------------------------------
//          mainly for input reading or for a generator  
 
void addedge( int n1, int n2, int weight ) {
 
	// dynamically extend arrays if too short
  if( dg[n1] == edge[n1].length ){
    edge[n1] = Arrays.copyOf( edge[n1], dg[n1]*2 ); 
    w[n1] = Arrays.copyOf( w[n1], dg[n1]*2 );
  }
	if( dg[n2] == edge[n2].length ){
    edge[n2] = Arrays.copyOf( edge[n2], dg[n2]*2 );
    w[n2] = Arrays.copyOf( w[n2], dg[n2]*2 );
  }
 
  // add edge
	edge[n1][dg[n1]] = n2;
	edge[n2][dg[n2]] = n1;
	w[n1][dg[n1]++] = w[n2][dg[n2]++] = weight;
  M++;
}
 
// ---------------------------- P R I N T  ------------------------------------
//                     useful for debug purposes 
 
void print(){
  for( int node = 0; node < N; node++) {
    System.out.printf("%2d__", node  );
    for( int j_neigh = 0; j_neigh < dg[node]; j_neigh++ )
      System.out.printf( " %2d_%2d", edge[node][j_neigh], w[node][j_neigh] );
    System.out.printf("\n");
  }
  System.out.printf("-------------------- \n");
}
 
// -------------------------  L O A D -----------------------------------------
 
static Graph load( String fileName ) { try {
  BufferedReader br;
  if( fileName == null || fileName.isEmpty()  )
    br = new BufferedReader( new InputStreamReader( System.in ) );
  else
    br = new BufferedReader( new FileReader( fileName ) ) ;
 
  StringTokenizer st = new StringTokenizer( br.readLine() );
  int n = Integer.valueOf( st.nextToken() );
  int m = Integer.valueOf( st.nextToken() );
 
  Graph g = new Graph( n );
 
  int n1, n2, weight;
  for( int i = 0; i < m; i++ ){
    st = new StringTokenizer( br.readLine() );
    n1 = Integer.valueOf( st.nextToken() );
    n2 = Integer.valueOf( st.nextToken() );
    weight = Integer.valueOf( st.nextToken() );
    g.addedge( n1, n2, weight );
  }
 
  return g;
	}
	catch ( IOException ee ) { System.out.printf(  ee.getMessage()+"\n"  ); return null;}
}
 
 
// ----------------------------------------------------------------------------
//                           G E N E R A T O R S
// ----------------------------------------------------------------------------
 
 
// -------------------------  Kn ----------------------------------------------
 static Graph generate_Kn( int n ){
   Graph g = new Graph( n );
   for( int n1 = 0; n1 < n-1; n1++ )
     for( int n2 = n1+1; n2 < n; n2++ )
       g.addedge( n1, n2, 0 );
   return g;
 }
 
 
// -------------------------  Kn ----------------------------------------------
 static Graph generate_Kn( int n, int lo, int hi, int seed ){
   Graph g = new Graph( n );
     Random ra = new Random(seed);
   for( int n1 = 0; n1 < n-1; n1++ )
     for( int n2 = n1+1; n2 < n; n2++ )
       g.addedge( n1, n2, lo + ra.nextInt(hi-lo+1) );
   return g;
 }
 
// -------------------------  Kmn ---------------------------------------------
  static Graph generate_Kmn( int m, int n ){
   Graph g = new Graph( n+m );
   for( int n1 = 0; n1 < n; n1++ )
     for( int n2 = n; n2 < n+m; n2++ )
       g.addedge( n1, n2, 0 );
   return g;
 }
 
// -------------------------  Cn ----------------------------------------------  
  static Graph generate_Cn( int n ){
   Graph g = new Graph( n );
   for( int n1 = 0; n1 < n-1; n1++ )
       g.addedge( n1, n1+1, 0 );
   g.addedge( 0, n-1, 0 );
   return g;
 }
 
// -------------------------  Pn ----------------------------------------------  
 static Graph generate_Pn( int n ){
   Graph g = new Graph( n );
   for( int n1 = 0; n1 < n-1; n1++ )
       g.addedge( n1, n1+1, 0 );
   return g;
 }
 
 
// -------------------------  Wn ----------------------------------------------  
  static Graph generate_Wn( int n ){
   Graph g = new Graph( n );
 
   for( int n1 = 1; n1 < n-1; n1++ ){
     g.addedge( 0,  n1, 0 );
     g.addedge( n1, n1+1, 0 );
   }
   g.addedge( 0, n-1, 0 );
   g.addedge( 1, n-1, 0 );
 
   for( int i = 0; i < n; i++ )
    Arrays.sort( g.edge[i], 0, g.dg[i] );
   return g;
 }
 
// -------------------- R A N D O M   P A T H ---------------------------------
 static Graph generate_rand_Pn( int n, int seed ){
   Random ra = new Random( seed );
   Graph g = new Graph( n );
   int [] perm = Graph.randPermutation( n, seed+1 );  // use another seed
   for( int i = 0; i < n-1; i++ )
       g.addedge( perm[i], perm[i+1], 0 );
   return g;
 }
// -------------------- R A N D O M   G R A P H -------------------------------
  static Graph randomGraph( int n, int m, int minW, int maxW, int seed ){
    Graph g = new Graph( n );
    g.addRandomEdges( m, seed );
    g.setRandWeights( minW, maxW, seed );
    return g;
  }
 
// -------------------- R A N D O M   G R A P H -------------------------------
  static Graph randomConnectedGraph( int n, int m, int minW, int maxW, int seed ){
    Graph g = Graph.generate_rand_Pn( n, seed );
    g.addRandomEdges( m - (g.N-1) , seed );
    g.setRandWeights( minW, maxW, seed );
    return g;
  }
 
  // -------------------- R A N D O M   E D G E S -----------------------------
  void addRandomEdges( int m, int seed ){
    if( m <= 0 ) return;
    long newM = Math.min( (long)M + m, ((long)N*(N-1))/2 );
 
    int j, n1, n2;
    Random ra = new Random( seed );
 
    while( M < newM ){
      n1 = ra.nextInt( N );
      n2 = ra.nextInt( N );
      if ( n1 == n2 )continue;
      // add if edge does not exist yet, slow check :-(
      if( dg[n1] < dg[n2] ){
        for( j = 0; j < dg[n1]; j++ )
          if( edge[n1][j] == n2 )break;
        if( j >= dg[n1] ) // n2 is not a neighbour of n1
          addedge( n1, n2, 0 );
      }
      else {
        for( j = 0; j < dg[n2]; j++ )
          if( edge[n2][j] == n1 )break;
        if( j >= dg[n2] )
            addedge( n1, n2, 0 );
      }
    } // add all edges  
  }
 
// -------------------- R A N D O M   W E I G H T S ---------------------------
  void setRandWeights( int minWeight, int maxWeight, int seed ){
    Random ra = new Random( seed );
    int k, neigh;
    for( int i = 0 ; i < N; i++ )
      for( int j = 0; j < dg[i]; j++ ){
        neigh = edge[i][j];
        if( i < neigh ) {
          k = 0; 
          while( edge[neigh][k] != i ) k++;
          w[i][j] = w[neigh][k] = minWeight+ ra.nextInt( maxWeight-minWeight+1 );
        }
      }
  }
 
// -------------------- R A N D O M   P E R M U T A T I O N -------------------
  static int[] randPermutation( int n, int seed ){
    int [] p = new int[n];
    for( int i = 0; i < n; i++ ) p[i] = i;
    int x, j;
    Random ra = new Random( seed );
    for( int i = n-1; i > 0 ; i-- ){
      j = ra.nextInt( i+1 );
       x = p[i]; p[i] = p[j]; p[j] = x;
    }
    return p; 
  }
 
 
static void list (int [] a) {
  for( int x : a )
    System.out.printf("%2d ", x);
  System.out.printf("\n");
} 
 
static void listEdgeArr (int [] a) {
  for( int i = 0; i < a.length; i += 2 )
    System.out.printf( "[%d %d] ", a[i], a[i+1] );
  System.out.printf( "\n" );
} 
 
static void listEdgePred (int [] pred) {
  for( int i = 0; i < pred.length; i++ )
    if( i != pred[i] )
      System.out.printf( "[%d %d] ", i, pred[i]  );
  System.out.printf( "\n" );
} 
 
 
}

courses/laso2017/pokrocili/mst_codes.txt · Last modified: 2017/09/20 10:17 by berezovs