深度优先遍历
import java.util.*;
public class Main{
static int N = 100010, M = 2 * N, ans = N, idx, n;//idx存储当前用到了哪个点
static int[] h = new int[N];//n个头节点(头节点指向的值)
static int[] e = new int[M];//表示结点的值
static int[] ne = new int[M];//ne[i]表示的是下标为i的结点的下一个结点
static boolean[] st = new boolean[N];//用作标记是否遍历过
public static void add(int a, int b){
e[idx] = b;//先把b的值加进去
ne[idx] = h[a];//把idx作为h[a]的最新头节点,它的next值指向h[a]之前指向的值
h[a] = idx ++;//头节点h[a]指向了idx,然后idx++
}
public static int dfs(int u){
int res = 0;
st[u] = true;
int sum = 1;
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(ans, res);
return sum;
}
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
n = sc.nextInt();
for(int i = 1; i < N; i ++){
h[i] = -1;
}
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.print(ans);
}
}
广度优先遍历
import java.util.Scanner;
public class Main{
static int N = 100010, idx, n, m;
static int[] h = new int[N];//各个头节点
static int[] e = new int[N];//e[i]表示以i为下标的节点的值
static int[] ne = new int[N];//ne[i]表示以i为下标的结点的next结点
static int[] d = new int[N];//表示各个节点到结点1的距离
static int[] q = new int[N];//队列
//单链表的模板
public static void add(int a, int b){
e[idx] = b;
ne[idx] = h[a];
h[a] = idx ++;
}
public static int bfs(){
int hh = 0, tt = -1;//hh队列头,tt队列尾
d[1] = 0;//第一个点的距离为0
q[++ tt] = 1;//把第一个点加入队列
while(tt >= hh)//当队列不为空时
{
int t = q[hh ++];//把队头取出来
for(int i = h[t]; i != -1; i = ne[i])//遍历单链表
{
int s = e[i];//把t的邻接点取出来,用一个常量表示
if(d[s] == -1){//如果这个点是没有遍历过的
d[s] = d[t] + 1;//这个距离在原来距离的基础上加1
q[++ tt] = s;//在把这个点加入队列,方便后面的搜索遍历
}
}
}
return d[n];
}
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
n = sc.nextInt();
m = sc.nextInt();
for(int i = 1; i < N; i ++){
h[i] = -1;
d[i] = -1;
}
while(m -- > 0){
int a = sc.nextInt();
int b = sc.nextInt();
add(a, b);
}
System.out.print(bfs());
}
}
拓扑排序 (是针对有向图来说的,无向图没有拓扑排序)
import java.util.Scanner;
public class Main{
static int N = 100010, idx, n, m;
static int[] h = new int[N];
static int[] e = new int[N];
static int[] ne = new int[N];
static int[] d = new int[N];//表示点的入度
static int[] q = new int[N];//队列
//单链表的固定模板
public static void add(int a, int b){
e[idx] = b;
ne[idx] = h[a];
h[a] = idx ++;
}
public static boolean bfs(){
int hh = 0, tt = -1;
for(int i = 1; i <= n; i ++){
if(d[i] == 0){
q[++ tt] = i;//将所有入度为0的点入队
}
}
while(tt >= hh)//当队列不为空
{
int t = q[hh ++];//取出队头
for(int i = h[t]; i != -1; i = ne[i]){
int s = e[i];//队头这个点的邻接点
d[s] --;//这个邻接点的入度减1
if(d[s] == 0){//如果恰好入度为0了
q[++ tt] = s;//就把它加入队列
}
}
}
return tt == n - 1;//一共n个元素,因为从0开始,所以tt=n-1时结束
}
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
n = sc.nextInt();
m = sc.nextInt();
for(int i = 0; i < N; i ++){
h[i] = -1;//把各个头节点记为-1
}
while(m -- > 0){
int a = sc.nextInt();
int b = sc.nextInt();
add(a, b);
d[b] ++;//在输入数据的时候就要把入度记录下来
}
if(bfs()){
for(int i = 0; i < n; i ++){
System.out.print(q[i] + " ");//输出队列
}
}else{
System.out.print("-1");//如果拓扑序列不存在输出-1
}
}
}