0:有向图基础类:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
|
package
Digraph;
import
java.util.ArrayList;
//有向图
public
class
Digraph {
private
final
int
v;
//顶点数
private
int
E;
//边数
private
ArrayList<ArrayList<Integer>> adj;
//邻接表
public
Digraph(
int
v){
//v个顶点的图
this
.v = v;
this
.E =
0
;
adj =
new
ArrayList<>();
for
(
int
i=
0
;i<v;i++)
adj.add(
new
ArrayList<Integer>());
}
//添加边
public
void
addEdge(
int
u,
int
v){
adj.get(u).add(v);
E++;
}
//取顶点v可以直接到达的点
public
ArrayList<Integer> getAdj(
int
v){
return
adj.get(v);
}
//取反向图。所有边的方向变反。
public
Digraph reverse(){
Digraph g =
new
Digraph(v);
for
(
int
i=
0
;i<v;i++){
for
(Integer ele : getAdj(i)) {
g.addEdge(ele,i);
}
}
return
g;
}
public
int
getV(){
return
v;
}
public
int
getE(){
return
E;
}
}
|
1:有向图的
可达性:
无向图的
连通性:
2:多点可达性:是否存在一条从顶点集合中的任意顶点到达给定顶点v的有向路径.
应用: 如java的内存回收机制.对象为顶点,引用为边.无法被访问到的对象被回收内存.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
package
Digraph;
import
java.util.ArrayList;
//有向图的可达性
public
class
DirectedDFS {
private
boolean
[] isVisited;
//
public
DirectedDFS(Digraph G,
int
s){
//图G中从s可达的所有顶点
isVisited =
new
boolean
[G.getV()];
dfs(G,s);
}
//在G中找出从sources中的所有顶点可达的所有顶点
public
DirectedDFS(Digraph G,ArrayList<Integer> source){
isVisited =
new
boolean
[G.getV()];
for
(Integer u : source){
if
(!isVisited[u]) dfs(G, u);
}
}
//深度优先搜索
private
void
dfs(Digraph G,
int
s) {
isVisited[s] =
true
;
for
(Integer v : G.getAdj(s)) {
if
(!isVisited[v]){
dfs(G, v);
}
}
}
//v是否可达
public
boolean
marked(
int
v){
return
isVisited[v];
}
}
|
3:有向图中的环:
如果一个优先级限制问题中存在有向环,那么这个问题肯定是无解的.
4:寻找有向环.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
|
package
Digraph;
import
java.util.LinkedList;
//判断有向图是否有环.
public
class
DirectedCycle {
private
boolean
[] isVisted;
//顶点访问状态
private
int
[] edgeTo;
//顶点父子关系
private
LinkedList<Integer> cycle;
//有向环中的多有顶点
private
boolean
[] onStack;
//递归调用栈上的所有顶点.
public
DirectedCycle(Digraph G){
onStack =
new
boolean
[G.getV()];
isVisted =
new
boolean
[G.getV()];
edgeTo =
new
int
[G.getV()];
for
(
int
v=
0
;v<G.getV();v++){
if
(!isVisted[v]) dfs(G,v);
}
}
//dfs判断有向图是否有环
private
void
dfs(Digraph G,
int
v){
onStack[v] =
true
;
isVisted[v] =
true
;
for
(Integer w : G.getAdj(v)){
if
(
this
.hasCycle())
return
;
//如果已经找到环,则退出dfs递归
else
if
(!isVisted[w]){
edgeTo[w] = v;
//顶点w的前驱为v
dfs(G, w);
}
else
if
(onStack[w]){
//w已经被访问过,所以有环
cycle =
new
LinkedList<>();
for
(
int
x = v; x!=w;x=edgeTo[x]){
//环的轨迹
cycle.push(x);
}
cycle.push(w);
//环的起点
cycle.push(v);
//环的终点
}
}
}
private
boolean
hasCycle() {
return
cycle !=
null
;
}
}
|
5:(1)拓扑排序:给定一幅有向图,将所有的顶点排序,使得所有的有向边均从排在前边的元素指向排在后边的元素.
(2)优先级限制下的调度问题等价于计算有向无环图中的所有顶点和拓扑排序。
(3)有向无环图才可以进行拓扑排序。
(4)前序序列就是dfs()的调用顺序,后序序列就是顶点遍历完成的顺序。
(5)拓扑排序即为所有顶点的逆后序排列(与后序序列相反)。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
|
package
Digraph;
import
java.util.LinkedList;
//有向图基于深度优先搜索的顶点顺序
public
class
DepthFirstOrder {
private
boolean
[] isVisited;
private
LinkedList<Integer> pre;
//先序
private
LinkedList<Integer> post;
//后序
private
LinkedList<Integer> reversePost;
//逆后序
public
DepthFirstOrder(Digraph G){
pre =
new
LinkedList<>();
post =
new
LinkedList<>();
reversePost =
new
LinkedList<>();
isVisited =
new
boolean
[G.getV()];
for
(
int
v=
0
;v<G.getV();v++){
if
(!isVisited[v]) dfs(G,v);
}
}
//递归求各顶点顺序
private
void
dfs(Digraph g,
int
v) {
isVisited[v] =
true
;
pre.add(v);
//先序
for
(
int
w : g.getAdj(v)){
if
(!isVisited[w]){
dfs(g, w);
}
}
post.add(v);
//后序
reversePost.push(v);
//逆后序
}
public
LinkedList<Integer> getPre() {
return
pre;
}
public
void
setPre(LinkedList<Integer> pre) {
this
.pre = pre;
}
public
LinkedList<Integer> getPost() {
return
post;
}
public
void
setPost(LinkedList<Integer> post) {
this
.post = post;
}
public
LinkedList<Integer> getReversePost() {
return
reversePost;
}
//逆后序即为拓扑排序
public
void
setReversePost(LinkedList<Integer> reversePost) {
this
.reversePost = reversePost;
}
}
|
6:有向图的顶点对可达性,即u到v的可达性。 值几个用dfs即可。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
package
Digraph;
//顶点对的可达性
public
class
TransitiveClosure {
private
DirectedDFS[] all;
//邻接矩阵,表明v到w是否可达
public
TransitiveClosure(Digraph G){
all =
new
DirectedDFS[G.getV()];
for
(
int
i=
0
;i<G.getV();i++){
all[i] =
new
DirectedDFS(G,i);
}
}
//v到w是否可达
public
boolean
reachable(
int
v,
int
w){
return
all[v].marked(w);
}
}
|