目录

边上的权是附加的额外信息,可以代表不同公路的收费等你需要的信息。
- port java.io.File;
- import java.io.IOException;
- import java.util.Map;
- import java.util.TreeMap;
- import java.util.Scanner;
- import java.util.TreeSet;
-
- //暂时支持无向带权图
- public class WeightedGraph {
- private int V;
- private int E;
- //TreeMap传入的第二个元素是权值类型
- // 我们这里用的是Integer,具体用什么可以自行修改
- private TreeMap
[] adj; -
- public WeightedGraph(String file){
- File file = new File(filename);
- try(Scanner scanner = new Scanner(file)){
- V = scanner.nextInt();//读取顶点信息
- if(V < 0) throw new IllegalArgumentException("V must be non-negative");
- adj = new TreeMap[V];
- for(int i = 0; i < V; i++){
- adj[i] = new TreeMap
(); - }
-
- E = scanner.nextInt();//读取边的信息
- if(E < 0) throw new IllegalArgumentException("E must be non-negative");
-
- for(int i = 0; i < E; i++){
- int a = scanner.nextInt();
- validateVertex(a);
- int b = scanner.nextInt();
- validateVertex(b);//判断合法性
- int wight = scanner.nextInt();//读取权值
- //不要自环边
- if(a == b) throw new IllegalArgumentException("Self Loop is Detected!");
- //不要平行边
- if(adj[a].containsKey(b)) throw new IllegalArgumentException("");
-
- adj[a].put(b, weight);//传入weight
- adj[b].put(a, weight);
- }
- }
- catch(IOException e){
- e.printStackTrace();
- }
- }
- public void validateVertex(int v) {
- if (v < 0 || v >= V) {
- throw new IllegalArgumentException("vertex" + "is invalid");
- }
- }
- public int V() {return V;}
- public int E() {return E;}
-
- public boolean hasEdge(int v, int w){
- validateVertex(v);
- validateVertex(w);
- return adj[v].containsKey(w);
- }
- //返回和v相邻的所有顶点
- public Iterable
adj(int v){ - validateVertex(v);
- return adj[v].keySet();//返回TreeMap中所有的键
- }
- //返回权值
- public int getWeight(int v, int w){
- if(hasEdge(v, w))
- return adj[v].get(w);//获得w这个键对应的权值
- throw new IllegalArgumentException(String.format("no edge %d - %d", v, w));
- }
-
- public int degree(int v){
- validateVertex(v);
- return adj[v].size();
- }
- public void removeEdge(int v, int w){
- validateVertex(v);
- validateVertex(w);
- adj[v].remove(w);
- adj[w].remove(v);
- }
- @Override
- public Object clone(){
- try{
- WeightedGraph cloned = (WeightedGraph) super.clone();
- cloned.adj = new TreeMap[V];
- for(int v = 0; v < V; v++){
- cloned.adj[v] = new TreeMap
(); - for(Map.Entry
entry : adj[v].entrySet()) - cloned.adj[v].put(entry.getKey(), entry.getValue());
- }
- return cloned;
- }
- catch(CloneNotSupportedException e){
- e.printStackTrace();
- }
- return null;
- }
- @Override
- public String toString(){
- StringBuilder sb = new StringBuilder();
- sb.append(String.format("V = %d, E = %d\n"), V, E);
- for(int v = 0; v < V; v++){
- sb.append(String.format("%d : ", v));
- for(Map.Entry
entry : adj[v].entrySet()) - sb.append(String.format("(%d : %d)", entry.getKey(), entry.getValue()));
- sb.append('\n');
- }
- return sb.toString();
- }
-
- public static void main(String[]args){
- WeightedGraph g = new WeightedGraph("g.txt");
- System.out.println(g);
- }
-
- }
同一张图的不同生成树的权值和大小不同,最小生成树就是求权值和最小的生成树。

在选最短的边的同时要注意不要和已选的边形成环。如下图,我们成功选了六条边连接了七个顶点,形成了最小生成树。
切分定理

- import java.util.ArrayList;
- import java.util.Collections;
-
- public class Kruskal {
-
- private WeightedGraph G;
- private ArrayList
mst; -
- public Kruskal(WeightedGraph G){
-
- this.G = G;
- mst = new ArrayList<>();
-
- CC cc = new CC(G);
- if(cc.count() > 1) return;
-
- ArrayList
edges = new ArrayList<>(); - for(int v = 0; v < G.V(); v ++)
- for(int w: G.adj(v))
- if(v < w)
- edges.add(new WeightedEdge(v, w, G.getWeight(v, w)));
-
- Collections.sort(edges);
-
- UF uf = new UF(G.V());
- for(WeightedEdge edge: edges){
- int v = edge.getV();
- int w = edge.getW();
- if(!uf.isConnected(v, w)){
- mst.add(edge);
- uf.unionElements(v, w);
- }
- }
- }
-
- public ArrayList
result(){ - return mst;
- }
-
- public static void main(String[] args){
-
- WeightedGraph g = new WeightedGraph("g.txt");
- Kruskal kruskal = new Kruskal(g);
- System.out.println(kruskal.result());
- }
- }


- import java.util.ArrayList;
- import java.util.Queue;
- import java.util.PriorityQueue;
-
- public class Prim {
-
- private WeightedGraph G;
- private ArrayList
mst; -
- public Prim(WeightedGraph G){
-
- this.G = G;
- mst = new ArrayList<>();
-
- CC cc = new CC(G);
- if(cc.count() > 1) return;
-
- boolean visited[] = new boolean[G.V()];
- visited[0] = true;
- Queue pq = new PriorityQueue
(); - for(int w: G.adj(0))
- pq.add(new WeightedEdge(0, w, G.getWeight(0, w)));
-
- while(!pq.isEmpty()){
-
- WeightedEdge minEdge = (WeightedEdge) pq.remove();
- if(visited[minEdge.getV()] && visited[minEdge.getW()])
- continue;
-
- mst.add(minEdge);
-
- int newv = visited[minEdge.getV()] ? minEdge.getW() : minEdge.getV();
- visited[newv] = true;
- for(int w: G.adj(newv))
- if(!visited[w])
- pq.add(new WeightedEdge(newv, w, G.getWeight(newv, w)));
- }
- }
-
- public ArrayList
result(){ - return mst;
- }
-
- public static void main(String[] args){
-
- WeightedGraph g = new WeightedGraph("g.txt");
- Prim prim = new Prim(g);
- System.out.println(prim.result());
- }
- }

