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

● 二分图 1

 //+-----------------------------------------------------------------------------
// 第四章,二分图
package package01; import edu.princeton.cs.algs4.StdOut;
import edu.princeton.cs.algs4.StdRandom;
import edu.princeton.cs.algs4.GraphGenerator;
import edu.princeton.cs.algs4.Graph;
import edu.princeton.cs.algs4.Stack; public class class01
{
private boolean isBipartite;
private boolean[] color; // 顶点染色情况
private boolean[] marked;
private int[] edgeTo;
private Stack<Integer> cycle; // odd-length cycle public class01(Graph G)
{
isBipartite = true;
color = new boolean[G.V()];
marked = new boolean[G.V()];
edgeTo = new int[G.V()];
for (int v = 0; v < G.V(); v++)// 逐顶点深度优先遍历
{
if (!marked[v])
{
dfs(G, v);
}
}
} private void dfs(Graph G, int v)
{
marked[v] = true;
for (int w : G.adj(v))
{
if (cycle != null) // 已经有奇数环,停止递归
return;
if (!marked[w]) // 正常的标记、染色、继续递归
{
edgeTo[w] = v;
color[w] = !color[v];
dfs(G, w);
}
else if (color[w] == color[v]) // v ~ w 形成了长度为奇数的环
{
isBipartite = false;
cycle = new Stack<Integer>();
for (int x = v; x != w; x = edgeTo[x]) // 把从 v 到 w 的顶点压栈,保存有问题的环部分
cycle.push(x);
cycle.push(w);
}
}
} public boolean isBipartite()
{
return isBipartite;
} public boolean color(int v)
{
if (!isBipartite)
throw new UnsupportedOperationException("\n<color> Graph is not bipartite.\n");
return color[v];
} public Iterable<Integer> oddCycle()
{
return cycle;
} public static void main(String[] args)
{
int V1 = Integer.parseInt(args[0]); // 生成 G(V1 + V2, E) 顶点的二分图,再随机添加 F 条边
int V2 = Integer.parseInt(args[1]);
int E = Integer.parseInt(args[2]);
int F = Integer.parseInt(args[3]); Graph G = GraphGenerator.bipartite(V1, V2, E);
for (int i = 0; i < F; i++)
{
int v = StdRandom.uniform(V1 + V2);
int w = StdRandom.uniform(V1 + V2);
G.addEdge(v, w);
}
StdOut.println(G); class01 b = new class01(G);
if (b.isBipartite())
{
StdOut.println("Graph is bipartite");
for (int v = 0; v < G.V(); v++)
StdOut.println(v + ": " + b.color(v));
}
else
{
StdOut.print("Graph has an odd-length cycle: ");
for (int x : b.oddCycle())
StdOut.print(x + " ");
StdOut.println();
}
}
}

● 二分图 2

 package package01;

 import edu.princeton.cs.algs4.StdOut;
import edu.princeton.cs.algs4.StdRandom;
import edu.princeton.cs.algs4.GraphGenerator;
import edu.princeton.cs.algs4.Graph;
import edu.princeton.cs.algs4.Stack;
import edu.princeton.cs.algs4.Queue; public class class01
{
private boolean isBipartite; // 是否为二分图
private boolean[] color; // 顶点染色
private boolean[] marked;
private int[] edgeTo;
private Queue<Integer> cycle; // 存储了奇数长度的环(二分图则队列为空) public class01(Graph G)
{
isBipartite = true;
color = new boolean[G.V()];
marked = new boolean[G.V()];
edgeTo = new int[G.V()];
for (int v = 0; v < G.V() && isBipartite; v++)
{
if (!marked[v])
bfs(G, v); // 广度优先遍历
}
} private void bfs(Graph G, int s)
{
Queue<Integer> q = new Queue<Integer>();
color[s] = false; // 颜色使用 true / false
marked[s] = true;
for (q.enqueue(s); !q.isEmpty();)
{
int v = q.dequeue();
for (int w : G.adj(v))
if (!marked[w])
{
marked[w] = true;
edgeTo[w] = v;
color[w] = !color[v];
q.enqueue(w);
}
else if (color[w] == color[v]) // w 已经遍历过,且形成了奇数长度的环
{
isBipartite = false;
cycle = new Queue<Integer>();
Stack<Integer> stack = new Stack<Integer>();
int x = v, y = w; // 两端同时向回走,color[v] == color[w] 于是 color[x] == color[y]
for (; x != y; x = edgeTo[x], y = edgeTo[y]) // 存在节点 z 使得 edgeTo[x] == edgeTo[y] == z,循环结束时 x 和 y 均指向公共顶点 z
{
stack.push(x);
cycle.enqueue(y);
}
for (stack.push(x); !stack.isEmpty(); cycle.enqueue(stack.pop())); // 公共顶点 z 压栈,然后吐栈拼入队列,多一步是防止本来栈空
cycle.enqueue(w);
return;
}
}
} public boolean isBipartite()
{
return isBipartite;
} public boolean color(int v)
{
if (!isBipartite)
throw new UnsupportedOperationException("\n<color> Graph is not bipartite.\n");
return color[v];
} public Iterable<Integer> oddCycle()
{
return cycle;
} public static void main(String[] args)
{
int V1 = Integer.parseInt(args[0]);
int V2 = Integer.parseInt(args[1]);
int E = Integer.parseInt(args[2]);
int F = Integer.parseInt(args[3]);
Graph G = GraphGenerator.bipartite(V1, V2, E);
for (int i = 0; i < F; i++)
{
int v = StdRandom.uniform(V1 + V2);
int w = StdRandom.uniform(V1 + V2);
G.addEdge(v, w);
}
StdOut.println(G); class01 b = new class01(G);
if (b.isBipartite())
{
StdOut.println("Graph is bipartite");
for (int v = 0; v < G.V(); v++)
StdOut.println(v + ": " + b.color(v));
}
else
{
StdOut.print("Graph has an odd-length cycle: ");
for (int x : b.oddCycle())
StdOut.print(x + " ");
StdOut.println();
}
}
}

《算法》第四章部分程序 part 11的更多相关文章

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

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

  2. 《算法》第四章部分程序 part 18

    ▶ 书中第四章部分程序,包括在加上自己补充的代码,在有权有向图中寻找环,Bellman - Ford 算法求最短路径,套汇算法 ● 在有权有向图中寻找环 package package01; impo ...

  3. 《算法》第四章部分程序 part 16

    ▶ 书中第四章部分程序,包括在加上自己补充的代码,Dijkstra 算法求有向 / 无向图最短路径,以及所有顶点对之间的最短路径 ● Dijkstra 算法求有向图最短路径 package packa ...

  4. 《算法》第四章部分程序 part 15

    ▶ 书中第四章部分程序,包括在加上自己补充的代码,Kruskal 算法和 Boruvka 算法求最小生成树 ● Kruskal 算法求最小生成树 package package01; import e ...

  5. 《算法》第四章部分程序 part 14

    ▶ 书中第四章部分程序,包括在加上自己补充的代码,两种 Prim 算法求最小生成树 ● 简单 Prim 算法求最小生成树 package package01; import edu.princeton ...

  6. 《算法》第四章部分程序 part 10

    ▶ 书中第四章部分程序,包括在加上自己补充的代码,包括无向图连通分量,Kosaraju - Sharir 算法.Tarjan 算法.Gabow 算法计算有向图的强连通分量 ● 无向图连通分量 pack ...

  7. 《算法》第四章部分程序 part 9

    ▶ 书中第四章部分程序,包括在加上自己补充的代码,两种拓扑排序的方法 ● 拓扑排序 1 package package01; import edu.princeton.cs.algs4.Digraph ...

  8. 《算法》第四章部分程序 part 17

    ▶ 书中第四章部分程序,包括在加上自己补充的代码,无环图最短 / 最长路径通用程序,关键路径方法(critical path method)解决任务调度问题 ● 无环图最短 / 最长路径通用程序 pa ...

  9. 《算法》第四章部分程序 part 13

    ▶ 书中第四章部分程序,包括在加上自己补充的代码,图的前序.后序和逆后续遍历,以及传递闭包 ● 图的前序.后序和逆后续遍历 package package01; import edu.princeto ...

随机推荐

  1. Windows消息【一】 消息队列

    看了MSDN后,以下是我个人的理解! 消息能够被分为「队列化消息」和「非队列化消息」. 队列化消息是指当程序发生某事件时,由Windows主动捕获并把消息放入系统消息队列中,而程序在运行时会初始化一个 ...

  2. 查看耗时长,CPU 100% 的SQL

    [session_id], [request_id], [start_time] AS '开始时间', [status] AS '状态', [command] AS '命令', dest.[text] ...

  3. WPF Demo12 布局

    1 <Window x:Class="布局.DockPanel1" xmlns="http://schemas.microsoft.com/winfx/2006/x ...

  4. materializecss的水波纹效果

    参考http://www.materializecss.cn/waves.html <html lang="en"> <head> <meta cha ...

  5. 【Spring学习笔记-2.1】Spring的设值注入和构造注入

    设值注入: 先通过无参数的构造函数创建一个Bean实例,然后调用对应的setter方法注入依赖关系: 配置文件: <?xml version="1.0" encoding=& ...

  6. Ubuntn16.04.3配置root权限及启用root用户

    景 如果你是测试环境需要在VM中装了Ubuntn,安装完成后会创建一个Ubuntn的默认用户,默认用户因为权限的问题很多系统的配置文件不可以打开,默认是只读状态. 那么可以通过以下两种方式切换到roo ...

  7. vue-router总结2

    在上一篇总结了vue-router中的路由切换.重定向和路由传参等知识,因为篇幅的原因,便将剩下的路由模块化.路由嵌套.history模式.路由守卫等放在这里来写了.因为是继续前面的写.所以代码也还是 ...

  8. NodeJs使用async让代码按顺序串行执行

    描述 由于nodejs中的函数调用都是异步执行的,而笔者在工程开发中函数A需要四五个参数,而这四五个参数值都是通过函数调用获得,因此按顺序写代码时,执行到函数A时,往往函数A需要的参数值因为参数的异步 ...

  9. [ZZ]知名互联网公司Python的16道经典面试题及答案

    知名互联网公司Python的16道经典面试题及答案 https://mp.weixin.qq.com/s/To0kYQk6ivYL1Lr8aGlEUw 知名互联网公司Python的16道经典面试题及答 ...

  10. 计算机存储单位KB,MB,GB,TB,PB,EB,ZB,YB后面是什么?

    关于计算机存储单位KB,MB,GB,TB,PB,EB,ZB,YB后面是什么? 我们知道Kb是1000的1次方,所以 MB就是1000的2次方(106) GB就是1000的3次方(109) TB就是10 ...