zoukankan      html  css  js  c++  java
  • Minimum Spanning Tree

    1. Greedy Algorithms

      Aside from Dynamic Programming, Greedy Algorithm is another kind of optimization maneuver, in which every time we make a locally optimal choice and finally get the global optimum. According to CLRS, a problem exhibits Optimal Substructure if an optimal solution to the problem contains optimal solutions to the sub-problems. A good case in point may be Huffman Coding, which generates optimal prefix code in light of the frequencies of different symbols. Here is my solution to an SJTU ACM Online Judge problem concerning such coding strategy:

     1 import java.util.*;
     2 
     3 class Huffman {
     4     private class Node {
     5         public int freq, sum;
     6         
     7         public Node(int freq,int sum) {
     8             this.freq = freq;
     9             this.sum = sum;
    10         }
    11     }
    12     private int size, len;
    13     private Node[] arr;
    14     
    15     public Huffman() {
    16         size = 50000;
    17         arr = new Node[size];
    18     }
    19     public void doubleSpace() {
    20         Node[] tmp = arr;
    21         arr = new Node[size<<1];
    22         for (int i=0;i<size;i++) {
    23             arr[i] = tmp[i];
    24         }
    25         size <<= 1;
    26     }
    27     public void getLeaf(int f) {
    28         if (len==size) {
    29             doubleSpace();
    30         }
    31         arr[len++] = new Node(f,0);
    32     }
    33     public int freqSum() {
    34         // Return the weighted sum of prefix code length
    35         PriorityQueue<Node> q = new PriorityQueue<Node>(len,
    36                 new Comparator<Node>() {
    37                     public int compare(Node a,Node b) {
    38                         if (a.freq<b.freq) {
    39                             return -1;
    40                         } else if (a.freq>b.freq) {
    41                             return 1;
    42                         } else {
    43                             return 0;
    44                         }
    45                     }
    46                 }
    47         );
    48         for (int i=0;i<len;i++) {
    49             q.add(arr[i]);
    50         }
    51         while (q.size()>1) {
    52             Node a = q.poll(), b = q.poll();
    53             q.add(new Node(a.freq+b.freq,a.freq+b.freq+a.sum+b.sum));
    54         }
    55         return q.peek().sum;
    56     }
    57 }
    58 
    59 public class Main {
    60     public static void main(String[] args) {
    61         Huffman tree = new Huffman();
    62         Scanner in = new Scanner(System.in);
    63         int n=in.nextInt(),tmp;
    64         for (int i=0;i<n;i++) {
    65             tmp = in.nextInt();
    66             tree.getLeaf(tmp);
    67         }
    68         System.out.println(tree.freqSum());
    69         in.close();
    70     }
    71 }

    2. Prim's Algorithm

      To find a Minimal Spanning Tree of a given weighted graph, Prim's Algorithm is a greedy strategy in which we always choose an optimal vertex and connect it to the spanning tree. The following code is my solution to the USACO training problem "agrinet":

     1 import java.io.*;
     2 import java.util.*;
     3 
     4 public class agrinet {
     5     public static final int INF = 100001;
     6     public static Scanner input;
     7     public static PrintWriter output;
     8     public static int num;
     9     public static int [][] cost;
    10     
    11     public static int genMST() {
    12         // Prim's Algorithm based on Adjacency Matrix:
    13         int val=0, pos=0;
    14         boolean vis[] = new boolean [num];
    15         int dist[] = new int [num];
    16         vis[0] = true;
    17         for (int i=1;i<num;i++) {
    18             dist[i] = INF;
    19         }
    20         for (int i=1;i<num;i++) {
    21             for (int j=0;j<num;j++) {
    22                 // update all the remaining vertices
    23                 if (!vis[j] && dist[j]>cost[pos][j])
    24                     dist[j] = cost[pos][j];
    25             }
    26             dist[pos] = INF;
    27             for (int j=0;j<num;j++) {
    28                 // search for an optimal vertex
    29                 if (!vis[j] && dist[j]<dist[pos]) {
    30                     pos = j;
    31                 }
    32             }
    33             vis[pos] = true;
    34             val += dist[pos];
    35         }
    36         return val;
    37     }
    38     public static void main(String[] args) throws IOException {
    39         input = new Scanner(new FileReader("agrinet.in"));
    40         num = input.nextInt();
    41         cost = new int[num][num];
    42         for (int i=0;i<num;i++) {
    43             for (int j=0;j<num;j++) {
    44                 cost[i][j] = input.nextInt();
    45             }
    46         }
    47         input.close();
    48         output = new PrintWriter(new FileWriter("agrinet.out"));
    49         output.println(genMST());
    50         output.close();
    51     }
    52 }


    3. Kruskal's Algorithm

      Kruskal's Algorithm is another greedy method to build a Minimal Spanning Tree, in which every time we add an optimal safe edge to an edge set. Here I provide my solution an SJTU ACM Online Judge  problem as an example:

      1 import java.util.*;
      2 
      3 class DisjointSet {
      4     private int[] root;    // root of each item
      5     private int size;         // number of items
      6     
      7     public DisjointSet(int size) {
      8         if (size<=0) {
      9             throw new RuntimeException("Illegal Initial Size");
     10         } else {
     11             this.size = size;
     12             root = new int[size];
     13             for (int i=0;i<size;i++) {
     14                 root[i] = -1;
     15             }
     16         }
     17     }
     18     public void union(int i,int j) {
     19         // Merge the set of i and the set of j
     20         if (i<0||i>=size||j<0||j>=size) {
     21             throw new RuntimeException("IndexOutOfBounds on union");
     22         } else {
     23             i = find(i);
     24             j = find(j);
     25             if (i!=j) {    
     26                 // BEWARE that i and j may be identical
     27                 if (root[i]<root[j]) {
     28                     root[i] += root[j];
     29                     root[j] = i;
     30                 } else {
     31                     root[j] += root[i];
     32                     root[i] = j;
     33                 }
     34             }
     35         }
     36     }
     37     public int find(int idx)  {
     38         // Determine and return root[idx]
     39         if (idx<0||idx>=size) {
     40             throw new RuntimeException("IndexOutOfBounds on find");
     41         } else {
     42             int prev = root[idx];
     43             if (prev<0) {
     44                 return idx;
     45             } else {
     46                 root[idx] = find(prev);
     47                 return root[idx];
     48             }
     49         }
     50     }
     51 }
     52 
     53 class AdjList {
     54     private class Vert {
     55         public Edge next;
     56     }
     57     private class Edge {
     58         public int end, weight;
     59         public Edge next;
     60         
     61         public Edge(int end,int weight,Edge next) {
     62             this.end = end;
     63             this.weight = weight;
     64             this.next = next;
     65         }
     66     }
     67     private class HeapItem {
     68         public int start, end, weight;
     69         
     70         public HeapItem(int start,int end,int weight) {
     71             this.start = start;
     72             this.end = end;
     73             this.weight = weight;
     74         }
     75     }
     76     
     77     public static final int INF = 100001;
     78     private int num;
     79     private Vert [] vert;
     80     
     81     public AdjList(int num) {
     82         this.num = num;
     83         vert = new Vert[num];
     84         for (int i=0;i<num;i++) {
     85             vert[i] = new Vert();
     86         }
     87     }
     88     public void insert(int i,int j,int w) {
     89         if (i<j) {
     90             vert[i].next = new Edge(j,w,vert[i].next);
     91         } else {
     92             vert[j].next = new Edge(i,w,vert[j].next);
     93         }
     94     }
     95     public int genMST() {
     96         // Kruskal's Algorithm based on Adjacency List:
     97         DisjointSet set = new DisjointSet(num);
     98         PriorityQueue<HeapItem> q = new PriorityQueue<HeapItem>(INF,
     99                 new Comparator<HeapItem>() {
    100                     public int compare(HeapItem a,HeapItem b) {
    101                         if (a.weight<b.weight) {
    102                             return -1;
    103                         } else if (a.weight>b.weight) {
    104                             return 1;
    105                         } else {
    106                             return 0;
    107                         }
    108                     }
    109                 }
    110         );
    111         for (int i=0;i<num;i++) {
    112             Edge itr = vert[i].next;
    113             while (itr!=null) {
    114                 q.add(new HeapItem(i,itr.end,itr.weight));
    115                 itr = itr.next;
    116             }
    117         }
    118         int cnt=0, val=0;
    119         while (cnt<num-1) {
    120             HeapItem e = q.poll();
    121             if (set.find(e.start)!=set.find(e.end)) {
    122                 set.union(e.start,e.end);
    123                 val += e.weight;
    124                 cnt++;
    125             }
    126         }
    127         return val;
    128     }
    129 }
    130 
    131 public class Main {
    132     public static void main(String[] args) {
    133         Scanner in = new Scanner(System.in);
    134         int v = in.nextInt();
    135         int e = in.nextInt();
    136         AdjList g = new AdjList(v);
    137         for (int i=0;i<e;i++) {
    138             int j = in.nextInt()-1;
    139             int k = in.nextInt()-1;
    140             int w = in.nextInt();
    141             g.insert(j,k,w);
    142         }
    143         in.close();
    144         System.out.println(g.genMST());
    145     }
    146 }


     

    References:

        1. Cormen, T. H. et al. Introduction to Algorithms [M] .  北京:机械工业出版社, 2006-09

  • 相关阅读:
    JAVA——return浅析
    JAVA泛型【转】
    C#——WinForm修改密码
    java获取当前时间的方式【转】
    iOS 取得单张系统图片
    iOS UIView的简单渐变效果
    UIView 添加子视图的常用方法
    IOS之UIView的tag学习
    OC学习笔记之属性详解和易错点
    oc对象函数什么时候返回值类型使用instancetype
  • 原文地址:https://www.cnblogs.com/DevinZ/p/4411434.html
Copyright © 2011-2022 走看看