树就是特殊的图。树是无环并且联通的图
所以我们可以直接用存储树的方式来存储图。
图分为有向图和无向图。有向图:a->b无向图:a->b && b->a
无向图就是一种特殊的有向图,对于每一个边建两条边就行了
有向图的存储分类两大类:
1.邻接矩阵
开一个二维数组,g[a,b]就代表一条a指向b的边(一般不用,比较费空间o(n^2)),适用于稠密图)
2.邻接表
如果我们有n个点就开n个单链表(数组实现的单链表)
每个单链表表示这个节点等到达的所有的点。
将每个单链表的头节点用h数组存起来h[N]。当我们要新增一条有a指向b的边是,就让节点b头插到h[a]中。
例题:活动 - AcWing 系统讲解常用算法与数据结构,给出相应代码模板,并会布置、讲解相应的基础算法题目。https://www.acwing.com/problem/content/848/参考代码:
import java.util.*;
public class Main {
static int N = 100010,M = N*2;
//存n个单链表的链表头
static int[] h = new int[N];
//存每一个节点的值是多少
static int[] e = new int[M];
//存每一个节点的next指针是多少
static int[] ne = new int[M];
static int idx = 0,n;
//用来存哪些节点已经被遍历过了。每个节点只会被遍历一次
static boolean[] st = new boolean[N];
static int ans = N;
//邻接表的初始化,让所有的头全部指向-1
public static void init() {
for(int i = 0;i<h.length;i++) {
h[i] = -1;
}
}
//插入一条a指向b的边
public static void add(int a,int b) {
e[idx] = b;
ne[idx] = h[a];
h[a] = idx++;
}
//深度优先搜索
//返回以U为根个子树中的点的数量
public static int dfs(int u) {
st[u] = true;
int sum = 1,res = 0;
for(int i = h[u];i != -1;i = ne[i]) {
int j = e[i];
if (!st[j]) {
int s = dfs(j);
res = Math.max(res,s);
sum += s;
}
}
res = Math.max(res,n - sum);
ans = Math.min(res,ans);
return sum;
}
public static void main(String[] args) {
init();
Scanner sc = new Scanner(System.in);
n = sc.nextInt();
for(int i = 0;i<n - 1;i++) {
int a = sc.nextInt();
int b = sc.nextInt();
add(a,b);
add(b,a);
}
dfs(1);
System.out.println(ans);
}
}