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

▶ 书中第四章部分程序,包括在加上自己补充的代码,二分图的判定和染色

● 二分图 1

  1 //+-----------------------------------------------------------------------------
  2 // 第四章,二分图
  3 package package01;
  4 
  5 import edu.princeton.cs.algs4.StdOut;
  6 import edu.princeton.cs.algs4.StdRandom;
  7 import edu.princeton.cs.algs4.GraphGenerator;
  8 import edu.princeton.cs.algs4.Graph;
  9 import edu.princeton.cs.algs4.Stack;
 10 
 11 public class class01
 12 {
 13     private boolean isBipartite;
 14     private boolean[] color;            // 顶点染色情况
 15     private boolean[] marked;
 16     private int[] edgeTo;
 17     private Stack<Integer> cycle;       // odd-length cycle
 18 
 19     public class01(Graph G)
 20     {
 21         isBipartite = true;
 22         color = new boolean[G.V()];
 23         marked = new boolean[G.V()];
 24         edgeTo = new int[G.V()];
 25         for (int v = 0; v < G.V(); v++)// 逐顶点深度优先遍历
 26         {
 27             if (!marked[v])
 28             {
 29                 dfs(G, v);
 30             }
 31         }
 32     }
 33 
 34     private void dfs(Graph G, int v)
 35     {
 36         marked[v] = true;
 37         for (int w : G.adj(v))
 38         {
 39             if (cycle != null)                          // 已经有奇数环,停止递归
 40                 return;
 41             if (!marked[w])                             // 正常的标记、染色、继续递归
 42             {
 43                 edgeTo[w] = v;
 44                 color[w] = !color[v];
 45                 dfs(G, w);
 46             }
 47             else if (color[w] == color[v])              // v ~ w 形成了长度为奇数的环
 48             {
 49                 isBipartite = false;
 50                 cycle = new Stack<Integer>();
 51                 for (int x = v; x != w; x = edgeTo[x])  // 把从 v 到 w 的顶点压栈,保存有问题的环部分
 52                     cycle.push(x);
 53                 cycle.push(w);
 54             }
 55         }
 56     }
 57 
 58     public boolean isBipartite()
 59     {
 60         return isBipartite;
 61     }
 62 
 63     public boolean color(int v)
 64     {
 65         if (!isBipartite)
 66             throw new UnsupportedOperationException("\n<color> Graph is not bipartite.\n");
 67         return color[v];
 68     }
 69 
 70     public Iterable<Integer> oddCycle()
 71     {
 72         return cycle;
 73     }
 74 
 75     public static void main(String[] args)
 76     {
 77         int V1 = Integer.parseInt(args[0]); // 生成 G(V1 + V2, E) 顶点的二分图,再随机添加 F 条边
 78         int V2 = Integer.parseInt(args[1]);
 79         int E = Integer.parseInt(args[2]);
 80         int F = Integer.parseInt(args[3]);
 81 
 82         Graph G = GraphGenerator.bipartite(V1, V2, E);
 83         for (int i = 0; i < F; i++)
 84         {
 85             int v = StdRandom.uniform(V1 + V2);
 86             int w = StdRandom.uniform(V1 + V2);
 87             G.addEdge(v, w);
 88         }
 89         StdOut.println(G);
 90 
 91         class01 b = new class01(G);
 92         if (b.isBipartite())
 93         {
 94             StdOut.println("Graph is bipartite");
 95             for (int v = 0; v < G.V(); v++)
 96                 StdOut.println(v + ": " + b.color(v));
 97         }
 98         else
 99         {
100             StdOut.print("Graph has an odd-length cycle: ");
101             for (int x : b.oddCycle())
102                 StdOut.print(x + " ");
103             StdOut.println();
104         }
105     }
106 }

● 二分图 2

  1 package package01;
  2 
  3 import edu.princeton.cs.algs4.StdOut;
  4 import edu.princeton.cs.algs4.StdRandom;
  5 import edu.princeton.cs.algs4.GraphGenerator;
  6 import edu.princeton.cs.algs4.Graph;
  7 import edu.princeton.cs.algs4.Stack;
  8 import edu.princeton.cs.algs4.Queue;
  9 
 10 public class class01
 11 {
 12     private boolean isBipartite;   // 是否为二分图
 13     private boolean[] color;       // 顶点染色
 14     private boolean[] marked;      
 15     private int[] edgeTo;          
 16     private Queue<Integer> cycle;  // 存储了奇数长度的环(二分图则队列为空)
 17 
 18     public class01(Graph G)
 19     {
 20         isBipartite = true;
 21         color = new boolean[G.V()];
 22         marked = new boolean[G.V()];
 23         edgeTo = new int[G.V()];
 24         for (int v = 0; v < G.V() && isBipartite; v++)
 25         {
 26             if (!marked[v])
 27                 bfs(G, v);                          // 广度优先遍历
 28         }
 29     }
 30 
 31     private void bfs(Graph G, int s)
 32     {
 33         Queue<Integer> q = new Queue<Integer>();
 34         color[s] = false;                                           // 颜色使用 true / false
 35         marked[s] = true;
 36         for (q.enqueue(s); !q.isEmpty();)
 37         {
 38             int v = q.dequeue();
 39             for (int w : G.adj(v))
 40                 if (!marked[w])
 41                 {
 42                     marked[w] = true;
 43                     edgeTo[w] = v;
 44                     color[w] = !color[v];
 45                     q.enqueue(w);
 46                 }
 47                 else if (color[w] == color[v])                      // w 已经遍历过,且形成了奇数长度的环
 48                 {
 49                     isBipartite = false;
 50                     cycle = new Queue<Integer>();
 51                     Stack<Integer> stack = new Stack<Integer>();
 52                     int x = v, y = w;                               // 两端同时向回走,color[v] == color[w] 于是 color[x] == color[y]
 53                     for (; x != y; x = edgeTo[x], y = edgeTo[y])    // 存在节点 z 使得 edgeTo[x] == edgeTo[y] == z,循环结束时 x 和 y 均指向公共顶点 z                          
 54                     {
 55                         stack.push(x);
 56                         cycle.enqueue(y);
 57                     }
 58                     for (stack.push(x); !stack.isEmpty(); cycle.enqueue(stack.pop()));  // 公共顶点 z 压栈,然后吐栈拼入队列,多一步是防止本来栈空
 59                     cycle.enqueue(w);
 60                     return;
 61                 }
 62         }
 63     }
 64 
 65     public boolean isBipartite()
 66     {
 67         return isBipartite;
 68     }
 69 
 70     public boolean color(int v)
 71     {
 72         if (!isBipartite)
 73             throw new UnsupportedOperationException("\n<color> Graph is not bipartite.\n");
 74         return color[v];
 75     }
 76 
 77     public Iterable<Integer> oddCycle()
 78     {
 79         return cycle;
 80     }
 81 
 82     public static void main(String[] args)
 83     {
 84         int V1 = Integer.parseInt(args[0]);
 85         int V2 = Integer.parseInt(args[1]);
 86         int E = Integer.parseInt(args[2]);
 87         int F = Integer.parseInt(args[3]);
 88         Graph G = GraphGenerator.bipartite(V1, V2, E);
 89         for (int i = 0; i < F; i++)
 90         {
 91             int v = StdRandom.uniform(V1 + V2);
 92             int w = StdRandom.uniform(V1 + V2);
 93             G.addEdge(v, w);
 94         }
 95         StdOut.println(G);
 96 
 97         class01 b = new class01(G);
 98         if (b.isBipartite())
 99         {
100             StdOut.println("Graph is bipartite");
101             for (int v = 0; v < G.V(); v++)
102                 StdOut.println(v + ": " + b.color(v));
103         }
104         else
105         {
106             StdOut.print("Graph has an odd-length cycle: ");
107             for (int x : b.oddCycle())
108                 StdOut.print(x + " ");
109             StdOut.println();
110         }
111     }
112 }

猜你喜欢

转载自www.cnblogs.com/cuancuancuanhao/p/9824170.html