2024-01-30(树与图的深度优先遍历、广度优先遍历、拓扑排序)

846. 树的重心 - AcWing题库

深度优先遍历 

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);
    }
}

 

847. 图中点的层次 - AcWing题库 

 广度优先遍历

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());
    }
}

848. 有向图的拓扑序列 - AcWing题库

拓扑排序 (是针对有向图来说的,无向图没有拓扑排序)

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
        }
    }
}

 

  • 5
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值