本文最后更新于:January 27, 2022 pm
纸上得来终觉浅,绝知此事要躬行。路漫漫其修远兮,吾将上下而求索!知识是经过历史的巨人沉淀下来的,别总想着自己能够快速学会,多花点时间去看看,也许会发现些不同的东西。你能快速学会的、觉得简单的东西,对于别人来说也是一样的。人外有人,天外有天。当努力到达了一定的程度,幸运自会与你不期而遇。
目录 图的存储方式这里介绍三种:邻接矩阵、临接表、链式前向星。
邻接矩阵 这是最简单的,就是用二维数组实现。例如:G[a][b] = c;表示 a 点到 b 点之间的边的权重为 c 。
示例:
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 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 package acmtest;import java.io.*;import java.util.*;public class Main { public static BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); public static BufferedWriter out = new BufferedWriter(new OutputStreamWriter(System.out)); public static StreamTokenizer cin = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in))); public static PrintWriter cout = new PrintWriter(new OutputStreamWriter(System.out)); public static Scanner sc = new Scanner(System.in); public static int maxd = 1000 +7 ; public static void main (String[] args) throws Exception { int [][] G = new int [maxd][maxd]; int n = nextInt(); int m = nextInt(); while (m-->0 ) { int a = nextInt(); int b = nextInt(); int c = nextInt(); G[a][b] = c; G[b][a] = c; } for (int i=1 ;i<=n;++i) { for (int j=1 ;j<=n;++j) { System.out.print(G[i][j]); } System.out.println(); } closeAll(); } public static int nextInt () throws Exception { cin.nextToken(); return (int ) cin.nval; } public static long nextLong () throws Exception { cin.nextToken(); return (long ) cin.nval; } public static double nextDouble () throws Exception { cin.nextToken(); return cin.nval; } public static String nextString () throws Exception { cin.nextToken(); return cin.sval; } public static void closeAll () throws Exception { cout.close(); in.close(); out.close(); } }4 4 1 2 7 1 3 7 2 4 7 1 3 7 0770 7007 7000 0700
临接表 在C++中有一个STL容器叫作Vector,Java中也有,因为是线程安全的,所以效率低。而且也已经被弃用了。
Vector实现(不推荐,知道即可) 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 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 package acmtest;import java.io.*;import java.util.*;public class Main { public static BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); public static BufferedWriter out = new BufferedWriter(new OutputStreamWriter(System.out)); public static StreamTokenizer cin = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in))); public static PrintWriter cout = new PrintWriter(new OutputStreamWriter(System.out)); public static Scanner sc = new Scanner(System.in); public static int maxd = 1000 +7 ; public static void main (String[] args) throws Exception { int n = nextInt(); int m = nextInt(); Vector<Integer>[] v = new Vector[maxd]; for (int i=1 ;i<=n;++i) { v[i]= new Vector<>(); } while (m-->0 ) { int a = nextInt(); int b = nextInt(); v[a].add(b); v[b].add(a); } for (int i=1 ;i<=n;++i) { int len = v[i].size(); System.out.print(i+" " ); for (int j=0 ;j<len;++j) { System.out.print("-> " +v[i].get(j)); } System.out.println(); } closeAll(); } public static int nextInt () throws Exception { cin.nextToken(); return (int ) cin.nval; } public static long nextLong () throws Exception { cin.nextToken(); return (long ) cin.nval; } public static double nextDouble () throws Exception { cin.nextToken(); return cin.nval; } public static String nextString () throws Exception { cin.nextToken(); return cin.sval; } public static void closeAll () throws Exception { cout.close(); in.close(); out.close(); } }4 4 1 4 1 2 2 4 2 3 1 -> 4 -> 2 2 -> 1 -> 4 -> 3 3 -> 2 4 -> 1 -> 2
ArrayList实现 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 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 package acmtest;import java.awt.List;import java.io.*;import java.util.*;import com.sun.xml.internal.messaging.saaj.packaging.mime.util.LineInputStream;public class Main { public static BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); public static BufferedWriter out = new BufferedWriter(new OutputStreamWriter(System.out)); public static StreamTokenizer cin = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in))); public static PrintWriter cout = new PrintWriter(new OutputStreamWriter(System.out)); public static Scanner sc = new Scanner(System.in); public static int maxd = 1000 +7 ; public static void main (String[] args) throws Exception { int n = nextInt(); int m = nextInt(); ArrayList[] list = new ArrayList[maxd]; for (int i=1 ;i<=n;++i) { list[i]= new ArrayList<Integer>(); } while (m-->0 ) { int a = nextInt(); int b = nextInt(); list[a].add(b); list[b].add(a); } for (int i=1 ;i<=n;++i) { int len = list[i].size(); System.out.print(i+" " ); for (int j=0 ;j<len;++j) { System.out.print(" -> " +list[i].get(j)); } System.out.println(); } closeAll(); } public static int nextInt () throws Exception { cin.nextToken(); return (int ) cin.nval; } public static long nextLong () throws Exception { cin.nextToken(); return (long ) cin.nval; } public static double nextDouble () throws Exception { cin.nextToken(); return cin.nval; } public static String nextString () throws Exception { cin.nextToken(); return cin.sval; } public static void closeAll () throws Exception { cout.close(); in.close(); out.close(); } }4 4 1 4 1 3 2 3 2 4 1 -> 4 -> 3 2 -> 3 -> 4 3 -> 1 -> 2 4 -> 1 -> 2
LinkedList实现 同ArrayList实现一样的道理。只是把ArrayList
改成LinkedList
即可。不再演示。
链式前向星 实现的效果同临接表一样(存储方式也可以理解成临接表)。只不过是通过数组实现的。
用不同的方式实现链式前向星,本质一样,只是在增加边信息(add_edge()方法
)的实现方式不同。
方式一(Setter/Getter方法) 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 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 package acmtest;import java.awt.List;import java.io.*;import java.util.*;import com.sun.xml.internal.messaging.saaj.packaging.mime.util.LineInputStream;public class Main { public static BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); public static BufferedWriter out = new BufferedWriter(new OutputStreamWriter(System.out)); public static StreamTokenizer cin = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in))); public static PrintWriter cout = new PrintWriter(new OutputStreamWriter(System.out)); public static Scanner sc = new Scanner(System.in); public static int maxd = 1000 +7 ; public static class Edge { private int pre; private int to; private int w; public int getPre () { return pre; } public void setPre (int pre) { this .pre = pre; } public int getTo () { return to; } public void setTo (int to) { this .to = to; } public int getW () { return w; } public void setW (int w) { this .w = w; } } public static int node; public static int [] head = new int [maxd]; public static Edge[] edge = new Edge[maxd]; public static void init () { Arrays.fill(head, -1 ); node = 0 ; } public static void add_edge (int a,int b,int w) { edge[node]= new Edge(); edge[node].setTo(b); edge[node].setW(w); edge[node].setPre(head[a]); head[a]=node++; } public static void main (String[] args) throws Exception { int n = nextInt(); int m = nextInt(); init(); while (m-->0 ) { int a = nextInt(); int b = nextInt(); int c = nextInt(); add_edge(a, b, c); add_edge(b, a, c); } for (int i=1 ;i<=n;++i) { System.out.print(i+" " ); for (int j=head[i];j!=-1 ;j=edge[j].getPre()) { System.out.print(" -> " +edge[j].getTo()); } System.out.println(); } closeAll(); } public static int nextInt () throws Exception { cin.nextToken(); return (int ) cin.nval; } public static long nextLong () throws Exception { cin.nextToken(); return (long ) cin.nval; } public static double nextDouble () throws Exception { cin.nextToken(); return cin.nval; } public static String nextString () throws Exception { cin.nextToken(); return cin.sval; } public static void closeAll () throws Exception { cout.close(); in.close(); out.close(); } }4 4 1 4 7 1 3 7 2 4 7 3 4 7 1 -> 3 -> 4 2 -> 4 3 -> 4 -> 1 4 -> 3 -> 2 -> 1
此方式还有一种实现方法,在init()方法
中进行,上面的代码是在增加一条边的时候才声明一条边,现在就可以一次性把需要的边声明完。只是在声明的时候需要注意是无向图
还是有向图
。(边数相差两倍
)
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 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 package acmtest;import java.awt.List;import java.io.*;import java.util.*;import com.sun.xml.internal.messaging.saaj.packaging.mime.util.LineInputStream;public class Main { public static BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); public static BufferedWriter out = new BufferedWriter(new OutputStreamWriter(System.out)); public static StreamTokenizer cin = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in))); public static PrintWriter cout = new PrintWriter(new OutputStreamWriter(System.out)); public static Scanner sc = new Scanner(System.in); public static int maxd = 1000 +7 ; public static class Edge { private int pre; private int to; private int w; public int getPre () { return pre; } public void setPre (int pre) { this .pre = pre; } public int getTo () { return to; } public void setTo (int to) { this .to = to; } public int getW () { return w; } public void setW (int w) { this .w = w; } } public static int node; public static int [] head = new int [maxd]; public static Edge[] edge = new Edge[maxd]; public static void init (int m) { Arrays.fill(head, -1 ); for (int i=0 ;i<=m*2 ;++i) { edge[i] = new Edge(); } node = 0 ; } public static void add_edge (int a,int b,int w) { edge[node].setTo(b); edge[node].setW(w); edge[node].setPre(head[a]); head[a]=node++; } public static void main (String[] args) throws Exception { int n = nextInt(); int m = nextInt(); init(m); while (m-->0 ) { int a = nextInt(); int b = nextInt(); int c = nextInt(); add_edge(a, b, c); add_edge(b, a, c); } for (int i=1 ;i<=n;++i) { System.out.print(i+" " ); for (int j=head[i];j!=-1 ;j=edge[j].getPre()) { System.out.print(" -> " +edge[j].getTo()); } System.out.println(); } closeAll(); } public static int nextInt () throws Exception { cin.nextToken(); return (int ) cin.nval; } public static long nextLong () throws Exception { cin.nextToken(); return (long ) cin.nval; } public static double nextDouble () throws Exception { cin.nextToken(); return cin.nval; } public static String nextString () throws Exception { cin.nextToken(); return cin.sval; } public static void closeAll () throws Exception { cout.close(); in.close(); out.close(); } }
方式二(构造函数) 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 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 package acmtest;import java.awt.List;import java.io.*;import java.util.*;import com.sun.xml.internal.messaging.saaj.packaging.mime.util.LineInputStream;public class Main { public static BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); public static BufferedWriter out = new BufferedWriter(new OutputStreamWriter(System.out)); public static StreamTokenizer cin = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in))); public static PrintWriter cout = new PrintWriter(new OutputStreamWriter(System.out)); public static Scanner sc = new Scanner(System.in); public static int maxd = 1000 +7 ; public static class Edge { private int pre; private int to; private int w; public Edge () {} public Edge (int pre,int to,int w) { this .pre= pre; this .to= to; this .w= w; } public int getPre () { return pre; } public void setPre (int pre) { this .pre = pre; } public int getTo () { return to; } public void setTo (int to) { this .to = to; } public int getW () { return w; } public void setW (int w) { this .w = w; } } public static int node; public static int [] head = new int [maxd]; public static Edge[] edge = new Edge[maxd]; public static void init () { Arrays.fill(head, -1 ); node = 0 ; } public static void add_edge (int a,int b,int w) { edge[node]= new Edge(head[a],b,w); head[a]=node++; } public static void main (String[] args) throws Exception { int n = nextInt(); int m = nextInt(); init(); while (m-->0 ) { int a = nextInt(); int b = nextInt(); int c = nextInt(); add_edge(a, b, c); add_edge(b, a, c); } for (int i=1 ;i<=n;++i) { System.out.print(i+" " ); for (int j=head[i];j!=-1 ;j=edge[j].getPre()) { System.out.print(" -> " +edge[j].getTo()); } System.out.println(); } closeAll(); } public static int nextInt () throws Exception { cin.nextToken(); return (int ) cin.nval; } public static long nextLong () throws Exception { cin.nextToken(); return (long ) cin.nval; } public static double nextDouble () throws Exception { cin.nextToken(); return cin.nval; } public static String nextString () throws Exception { cin.nextToken(); return cin.sval; } public static void closeAll () throws Exception { cout.close(); in.close(); out.close(); } }4 4 1 4 7 1 3 7 2 4 7 3 4 7 1 -> 3 -> 4 2 -> 4 3 -> 4 -> 1 4 -> 3 -> 2 -> 1
数组实现链式前向星 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 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 import java.io.*;import java.math.BigInteger;import java.util.Arrays;import java.util.Scanner;public class Main { public static BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); public static BufferedWriter out = new BufferedWriter(new OutputStreamWriter(System.out)); public static StreamTokenizer cin = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in))); public static PrintWriter cout = new PrintWriter(new OutputStreamWriter(System.out)); public static Scanner sc = new Scanner(System.in); public static int maxd = 100000 +7 ; public static int INF = 0x3f3f3f3f ; public static int [] head = new int [maxd]; public static int [] edgePre = new int [maxd]; public static int [] edgeW = new int [maxd]; public static int [] edgeTo = new int [maxd]; public static int [] dis = new int [maxd]; public static boolean [] vis= new boolean [maxd]; public static int node = 0 ; public static void init (int n,int m) { for (int i=1 ;i<=n;++i) { head[i]=-1 ; dis[i]=INF; vis[i]=false ; } node=0 ; } public static void add_edge (int a,int b,int c) { edgeTo[node]=b; edgeW[node]=c; edgePre[node]=head[a]; head[a]=node++; } public static void main (String[] args) throws Exception { int n = nextInt(); int m = nextInt(); init(n,m); for (int i=1 ;i<=m;++i){ int a = nextInt(); int b = nextInt(); int c = nextInt(); add_edge(a,b,c); } cout.println(); cout.flush(); closeAll(); } public static void cinInit () { cin.wordChars('a' , 'z' ); cin.wordChars('A' , 'Z' ); cin.wordChars(128 + 32 , 255 ); cin.whitespaceChars(0 , ' ' ); cin.commentChar('/' ); cin.quoteChar('"' ); cin.quoteChar('\'' ); cin.parseNumbers(); } public static int nextInt () throws Exception { cin.nextToken(); return (int ) cin.nval; } public static long nextLong () throws Exception { cin.nextToken(); return (long ) cin.nval; } public static double nextDouble () throws Exception { cin.nextToken(); return cin.nval; } public static String nextString () throws Exception { cin.nextToken(); return cin.sval; } public static void closeAll () throws Exception { cout.close(); in.close(); out.close(); } }
拓扑排序 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 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 import java.io.*;import java.text.SimpleDateFormat;import java.util.*;public class Main { public static BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); public static BufferedWriter out = new BufferedWriter(new OutputStreamWriter(System.out)); public static StreamTokenizer cin = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in))); public static PrintWriter cout = new PrintWriter(new OutputStreamWriter(System.out)); public static Scanner sc = new Scanner(System.in); public static int maxd = 10000 +7 ; public static int INF = 0x3f3f3f3f ; public static int mod = 998244353 ; public static int [] head = new int [maxd]; public static int [] edgePre = new int [maxd]; public static int [] edgeTo = new int [maxd]; public static int [] num = new int [maxd]; public static int node = 0 ; public static PriorityQueue<Integer> q = new PriorityQueue<>(); public static Queue<Integer> v = new ArrayDeque<>(); public static void init (int n,int m) { for (int i=1 ;i<=n;++i) { head[i]=-1 ; } node=0 ; } public static void add_edge (int a,int b) { edgeTo[node]=b; edgePre[node]=head[a]; head[a]=node++; } public static void topo (int n) { for (int i=1 ;i<=n;++i){ if (num[i]==0 ) q.add(i); } while (!q.isEmpty()){ int now = q.poll(); v.add(now); for (int i=head[now];i!=-1 ;i=edgePre[i]){ int to = edgeTo[i]; num[to]--; if (num[to]==0 ) q.add(to); } } int len = v.size(); if (len==n){ for (int i=0 ;i<len;++i){ System.out.print(v.poll()+" " ); } }else { System.out.println("NO" ); } } public static void main (String[] args) throws Exception { int n = nextInt(); int m = nextInt(); init(n,m); for (int i=1 ;i<=m;++i){ int a = nextInt(); int b = nextInt(); add_edge(a,b); num[b]++; } topo(n); closeAll(); } public static void cinInit () { cin.wordChars('a' , 'z' ); cin.wordChars('A' , 'Z' ); cin.wordChars(128 + 32 , 255 ); cin.whitespaceChars(0 , ' ' ); cin.commentChar('/' ); cin.quoteChar('"' ); cin.quoteChar('\'' ); cin.parseNumbers(); } public static int log (int x) { return (int ) (Math.log(x)/Math.log(2 )); } public static int nextInt () throws Exception { cin.nextToken(); return (int ) cin.nval; } public static long nextLong () throws Exception { cin.nextToken(); return (long ) cin.nval; } public static double nextDouble () throws Exception { cin.nextToken(); return cin.nval; } public static String nextString () throws Exception { cin.nextToken(); return cin.sval; } public static void closeAll () throws Exception { cout.close(); in.close(); out.close(); } }
测试数据
输入:
6 8 1 2 1 3 1 4 3 2 3 5 4 5 6 4 6 5
输出: