阶段学习总结--树图存储遍历+搜索

本周完成的任务如下:

搜索练习题目完善

树与图的存储和遍历理解与掌握

树图与搜索结合的题目练习

1.树与图的存储

一般来说用邻接表来实现存树、图(邻接矩阵的话时间复杂度n²)(其实用vector来实现也可以,不过用数组模拟效率更高,虽然开始时会有些不适应,但理解后毕竟效率更高些)。思路是每个结点开一个单链表,存该节点的连通点。建立两个数组,分别存值和下个连通节点的下标,两个数组通过下标建立联系(无向图的话每次存边存两次有向边即可)。插入新增结点的话思路如下(这里的插入理解了好长时间,所以画了个图,防止以后自己忘记了...)

void add(int a, int b)
{
    e[idx] = b, ne[idx] = h[a], h[a] = idx ++ ;
}

2.树与图的遍历 

dfs思路:传入一个结点,从当前节点开始,标记结点是否已经遍历过,若没有,则枚举所有该节点的出边(连通点),若未标记,则递归深搜。即可完成该点的遍历。若题目要求各种情况,则遍历图:对每个结点都进行一次深搜。

bfs思路:当前节点标记已被遍历,结点入队,循环队列非空,每次取出队头,将未标记的且与当前结点连通的结点入队,并标记已被遍历,即可完成当前节点的遍历。需要遍历图则对每个节点进行广搜。

这里树与图搜索区分于之前的搜索主要是如何表示将连通点入队(如何枚举所有连通点/出边)。代码实现如下:

//dfs:
//h代表头节点,u是当前访问的结点,e存值,ne存连通点下标,st标记
for(int i=h[u];i!=-1;i=ne[i])
{
    int j=e[i];
    if(!st[j]) dfs(j);
}


//bfs:
for(int i=h[i];i!=-1;i=ne[i])
{
    int j=e[i];
    if(!st[i]){
        st[j]=true;
        q.push(j);
    }
}

 其实本质上跟前面练习的深搜广搜没有区别,主要是表示连通点需要新的思考。

3.树图存储与搜索结合相关题目

「JYLOI Round 1」箭头调度 - 洛谷

题意:给出n 个点 m 条边的无向图,确定给定点与点间边的方向,使其生成一个拓扑序列,且使得这个拓扑序是在所有可能的拓扑序中字典序第 k小的。

先将给出的边连通关系用邻接表存好,再用拓扑排序生成拓扑序列,最后卡在寻找字典序第k小的拓扑序。这道题收获是巩固了一下拓扑排序代码,思路:

遍历结点数组,先将入度为0的点入队(建图同时开一个数组记录点的入度),循环队列非空,取出头节点,寻找入度为0结点的连通点,每搜到一次入度-1,入度为0时入队,开一个数组,每个结点入队时记录,即可生成拓扑序列。

最大食物链计数 - 洛谷

题意:给出n种生物之间的m种吃与被吃的关系,求出食物链条数

高中生物知识,食物链即单向无环图,并且最左端是生产者,入度为0,可以想到拓扑排序,用一个答案数组记录每次入度为零的点入队即可。

[NOIP1996 提高组] 挖地雷 - 洛谷

 题意:存在地窖相连,且每个地窖中都有一定数量的地雷,求最多能挖到的雷数(不可回头)

图的存储+dfs遍历,遍历图中所有点,深搜,如果可以继续搜索,则更新最大值和答案数组,每次寻找连通点,若未走过,则进行标记,递归,回溯取消标记(老套路了),dfs参数记录当前位置、已走结点数、已挖到的雷数。

高手去散步 - 洛谷

题意:给出若干景点是否连通、穿梭两景点间所需时间,求耗时最长的方案。

即   无向图+边权的存储与遍历,求怎样走使边权加和最大。

这里存边权想了半天(其实存边权跟存其他的东西思路都一样,都是通过下标联系起来的),最后又是画图解决的(不得不说图真是帮助理解的神器..)

 这里点的值就显得没必要了,根据边权来进行dfs(用sum来记录最大值,更新即可)

总结一下,拿出来的时间还是不够多,题单靠后面的题目都只进行了读题思考+大体看看题解。虽说搜索专项练习结束了,但好像最近学的东西都离不开搜索hhh

发完博客才想起来cf Round#783(div.2)A题题解忘记写了...

思路是这样的:分成两段走,先从(1,1)走到(n,n),然后接下来每次横坐标回退然后向下靠近目标点,分别得出奇偶的规律,然后把走的步数加和即可(当时手动演算了挺多,其实可以直接打表演算更快能找到规律...)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值