写在前面
我们知道,图的表示法有很多,但是用多种方法来实现我们的算法,那就变的困难了,所以我们遇到图的时候就要想到转化为一般表示法,如果题目给的是别的表示方法,那么我们就进行转换,将题目给的图转化为我们的一般图表示法。
图的一般表示法
// 点结构的描述
public class Node {
public int value;//表示值
public int in;//入度:有多少个边指向此处
public int out;//出度:有多少指出去的边
public ArrayList<Node> nexts;//直接邻居,指向下一个的点集合
public ArrayList<Edge> edges;//边,从我出发的边的集合
//out=next.size()
public Node(int value) {
this.value = value;
in = 0;
out = 0;
nexts = new ArrayList<>();
edges = new ArrayList<>();
}
}
//边结构的描述
public class Edge {
public int weight;//边的权重
public Node from;//边的入点
public Node to;//边的出点
public Edge(int weight, Node from, Node to) {
this.weight = weight;
this.from = from;
this.to = to;
}
}
//图的结构
public class Graph {
public HashMap<Integer, Node> nodes;//k表示编号id,Node就是实际的点
public HashSet<Edge> edges;
public Graph() {
nodes = new HashMap<>();
edges = new HashSet<>();
}
}
转化
例一
题目所给的图的结构是这样描述的
- 用二维数组来表示图,共三个列,第一列表示边权,第二列表示入点id,第三列表示出点id。
- [ 边权 ,from ,to ] 三个都是int型的
// matrix 所有的边
// N*3 的矩阵
// [weight, from节点上面的值,to节点上面的值]
//
// [ 5 , 0 , 7]
// [ 3 , 0, 1]
//
public static Graph createGraph(int[][] matrix) {
Graph graph = new Graph();
for (int i = 0; i < matrix.length; i++) {
// 拿到每一条边, matrix[i]
int weight = matrix[i][0];
int from = matrix[i][1];
int to = matrix[i][2];
//给图加点
if (!graph.nodes.containsKey(from)) {
graph.nodes.put(from, new Node(from));
}
if (!graph.nodes.containsKey(to)) {
graph.nodes.put(to, new Node(to));
}
//建立边
Node fromNode = graph.nodes.get(from);
Node toNode = graph.nodes.get(to);
Edge newEdge = new Edge(weight, fromNode, toNode);
//添加fromNode的直接邻居
fromNode.nexts.add(toNode);
fromNode.out++;//fromNode的出度++
toNode.in++; //toNode的入度++
fromNode.edges.add(newEdge);//以fromNode开始的边
//给图加边
graph.edges.add(newEdge);
}
return graph;
}