蓝桥杯双周赛算法心得——串门(双链表数组+双dfs)

大家好,我是晴天学长,树和dfs的结合,其邻接表的存图方法也很重要。需要的小伙伴可以关注支持一下哦!后续会继续更新的。💪💪💪


1) .串门

在这里插入图片描述


2) .算法思路

串门(怎么存图很关键)
用双链表存
1.找到最长的那段路(树的最长直径)
2.答案=(总和)*2-最长那段路。

1.接受数据
2.建立标记数组,存图
3.从1开始找最大路径,并更新最大路径的点
4.从最大路径的点开始出发,再找最大路径
5.答案


3).算法步骤

1.读取输入的节点数量 n。
2.创建一个布尔数组 vis,用于记录节点的访问状态。
3.初始化变量 total 为节点数量 n。
4.将 n 减 1,并创建一个链表列表 list,用于存储图的边关系。
5.循环 n 次,读取边的起点 u、终点 v 和权重 w。
6.将路径和增加 w + w。
7.在 list 中的起点 u 处添加边的信息 [v, w]。
8.在 list 中的终点 v 处添加边的信息 [u, w]。
9.调用 dfs 方法进行第一次深度优先搜索,参数为起点 1,访问状态数组 vis 和初始路径和 0。
10.重置访问状态数组 vis 为初始状态,最大路径和 maxsum 为 0。
11.调用 dfs 方法进行第二次深度优先搜索,参数为节点编号 nodeindex,访问状态数组 vis 和初始路径和 0。
12.计算最终结果,输出 totalsum - maxsum。


4). 代码实例

package LanQiaoTest.DFS;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Scanner;

public class 串门 {
    static List<List<int[]>> list = new ArrayList<>();
    static long maxsum = 0;
    static int nodeindex = 0;
    static long totalsum = 0;

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int n = scanner.nextInt();
        boolean[] vis = new boolean[n + 10];
        int total = n ;
        n--;
        //建立链表
        for (int i = 0; i < n + 10; i++) {
            list.add(new ArrayList<>());
        }
        //接受数据,存图(树)
        while (n > 0) {
            int u = scanner.nextInt();
            int v = scanner.nextInt();
            int w = scanner.nextInt();
            //添加路径和
            totalsum += w + w;
            // 两个路径都可以走
            list.get(u).add(new int[]{v, w});
            list.get(v).add(new int[]{u, w});
            n--;
        }
        //开始第一次的dfs
        dfs(1, vis, 0);
        //第一次结束,开始第二次
        vis = new boolean[total + 10];
        maxsum = 0;
        // 开始找第二次
        dfs(nodeindex, vis, 0);
        System.out.println(totalsum - maxsum);
    }

    public static void dfs(int start, boolean[] vis, long sum) {
        //避免往回走
        vis[start] = true;
        if (sum > maxsum) {
            maxsum = sum;
            nodeindex = start;
        }
        //开枝散叶
        for (int i = 0; i < list.get(start).size(); i++) {
            int[] temp = list.get(start).get(i);
            //没有标记,就走下去
            if (!vis[temp[0]]) {
                dfs(temp[0], vis, sum+temp[1]);
            }
        }
        //也可以不回溯,因为跟随着的是返回结果,不会在重复的走下去了,回溯也行。
        vis[start]=false;
    }
}


4).总结

  • 图(树的)正确遍历。
  • dfs(回溯)

试题链接:

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

晴天学长

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值