个人博客
www.tothefor.com
蓝桥杯复习知识点汇总
目录
图的存储方式这里介绍三种:邻接矩阵、临接表、链式前向星。
邻接矩阵
这是最简单的,就是用二维数组实现。例如:G[a][b] = c;表示 a 点到 b 点之间的边的权重为 c 。
示例:
package acmtest;
import java.io.*;
import java.util.*;
/**
* @Author DragonOne
* @Date 2021/12/11 07:13
* @墨水记忆 www.tothefor.com
*/
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(); //n个点
int m = nextInt(); //m条边
while(m-->0) {
int a = nextInt(); //a点(起点)
int b = nextInt(); //b点(终点)
int c = nextInt(); //边的权重
//有向图
// G[a][b] = c; //a->b
// 无向图
G[a][b] = c; //a->b
G[b][a] = c; //b->a
}
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实现(不推荐,知道即可)
package acmtest;
import java.io.*;
import java.util.*;
/**
* @Author DragonOne
* @Date 2021/12/11 07:13
* @墨水记忆 www.tothefor.com
*/
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(); //n个点
int m = nextInt(); //m条边
Vector<Integer>[] v = new Vector[maxd];
for(int i=1;i<=n;++i) {
v[i]= new Vector<>();
}
while(m-->0) {
int a = nextInt(); //a点(起点)
int b = nextInt(); //b点(终点)
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实现
package acmtest;
import java.io.*;
import java.util.*;
/**
* @Author DragonOne
* @Date 2021/12/11 07:13
* @墨水记忆 www.tothefor.com
*/
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(); //n个点
int m = nextInt(); //m条边
ArrayList[] list = new ArrayList[maxd];
for(int i=1;i<=n;++i) {
list[i]= new ArrayList<Integer>();
}
while(m-->0) {
int a = nextInt(); //a点(起点)
int b = nextInt(); //b点(终点)
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方法)
package acmtest;
import java.io.*;
import java.util.*;
/**
* @Author DragonOne
* @Date 2021/12/11 07:13
* @墨水记忆 www.tothefor.com
*/
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; // pre表示与这条边同起点的上一条边所在结点的编号
private int to; // 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]; //点集 head[i]表示以i为起点的最后一条边所在结点的编号
public static Edge[] edge = new Edge[maxd]; //存储边信息
//初始化
public static void init() {
Arrays.fill(head, -1); //-1表示没有边
node = 0;
}
//增加边信息,a点到b点的边权重为w
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(); //n个点
int m = nextInt(); //m条边
init();
while(m-->0) {
int a = nextInt(); //a点(起点)
int b = nextInt(); //b点(终点)
int c = nextInt(); //边的权重
//有向图
// add_edge(a, b, c); //a->b
//无向图
add_edge(a, b, c); //a->b
add_edge(b, a, c); //b->a
}
for(int i=1;i<=n;++i) {
System.out.print(i+" ");
for(int j=head[i];j!=-1;j=edge[j].getPre()) { //不断寻找当前点的上一条边,没有边(为-1时)则结束
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()方法
中进行,上面的代码是在增加一条边的时候才声明一条边,现在就可以一次性把需要的边声明完。只是在声明的时候需要注意是无向图
还是有向图
。(边数相差两倍
)
package acmtest;
import java.io.*;
import java.util.*;
/**
* @Author DragonOne
* @Date 2021/12/11 07:13
* @墨水记忆 www.tothefor.com
*/
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; // pre表示与这条边同起点的上一条边所在结点的编号
private int to; // 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]; //点集 head[i]表示以i为起点的最后一条边所在结点的编号
public static Edge[] edge = new Edge[maxd]; //存储边信息
//初始化
public static void init(int m) {
Arrays.fill(head, -1); //-1表示没有边
for(int i=0;i<=m*2;++i) { //这里是无向图,所以边数要乘2。必须要从0开始,因为边的编号是从0开始的,即node是从0开始的
edge[i] = new Edge();
}
node = 0;
}
//增加边信息,a点到b点的边权重为w
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(); //n个点
int m = nextInt(); //m条边
init(m);
while(m-->0) {
int a = nextInt(); //a点(起点)
int b = nextInt(); //b点(终点)
int c = nextInt(); //边的权重
//有向图
// add_edge(a, b, c); //a->b
//无向图
add_edge(a, b, c); //a->b
add_edge(b, a, c); //b->a
}
for(int i=1;i<=n;++i) {
System.out.print(i+" ");
for(int j=head[i];j!=-1;j=edge[j].getPre()) { //不断寻找当前点的上一条边,没有边(为-1时)则结束
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();
}
}
方式二(构造函数)
package acmtest;
import java.io.*;
import java.util.*;
/**
* @Author DragonOne
* @Date 2021/12/11 07:13
* @墨水记忆 www.tothefor.com
*/
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; // pre表示与这条边同起点的上一条边所在结点的编号
private int to; // 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]; //点集 head[i]表示以i为起点的最后一条边所在结点的编号
public static Edge[] edge = new Edge[maxd]; //存储边信息
//初始化
public static void init() {
Arrays.fill(head, -1); //-1表示没有边
node = 0;
}
//增加边信息,a点到b点的边权重为w
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(); //n个点
int m = nextInt(); //m条边
init();
while(m-->0) {
int a = nextInt(); //a点(起点)
int b = nextInt(); //b点(终点)
int c = nextInt(); //边的权重
//有向图
// add_edge(a, b, c); //a->b
//无向图
add_edge(a, b, c); //a->b
add_edge(b, a, c); //b->a
}
for(int i=1;i<=n;++i) {
System.out.print(i+" ");
for(int j=head[i];j!=-1;j=edge[j].getPre()) { //不断寻找当前点的上一条边,没有边(为-1时)则结束
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