PAT Note

include头文件可以使用#include<bits/stdc++.h>替代

代码截图摘自柳婼

1003.

急救,找到最短路径,最短路径的条数,并找到最短路径一路上的点权和

使用dijkstra算法:

声明数组e[510][510] 邻接矩阵用于表明结点之间的连接情况;

在最开始时,将邻接矩阵赋值为极大值。

 

将起点的dis[c1]赋值为0后,在第一次处理中,肯定是起始结点是最小值,将起点在visit中的索引设置为true,判断剩余的所有节点,如果结点没有被访问过,且结点之间的距离非无穷大,则更新dis[u]结点的距离。实际上就是更新所有与起点邻接的点。

下一次则找没有访问过的,最近的结点,将其visit的索引设置为true,然后更新这个结点的所有邻接结点的dis值。

  1. 找到没有访问过的 dis最小的结点
  2. 将该节点的visit设置为true,标记访问过;
  3. 将该节点的所有邻接结点的距离更新;
  4. 跳回步骤1

1013.battel over cities

一堆城市,城市之间有高速公路连接,如果一个城市被占领,至少需要几条高速公路将城市连接起来。

解决方法:将问题转化为连通域分量问题,如果有a个连通分量,则只需要修a-1个高速公路即可连接起来

  1. 将相邻的城市读入邻接矩阵,将相邻的矩阵的值设置为1;
  2. 将所有城市的visit矩阵设置为false,将被占领的城市的访问设置为true,这样这个城市就不会被访问了

对每个结点调用dfs,每个dfs会将所有与当前结点连接的结点的访问设置为ture,一共调用了几次dfs,即有几个联通分量。

  1. dfs

 

1018.

公共自行车管理,要求将目标点的自行车数量改为平衡,一路上可以带去自行车,回来的时候可以把自行车带回

找出最短路径,如果有多条相同的最短路径,则找出需要带去或者带回自行车数量最少的路径

  1. 调用dijkstra算法,得到从根结点开始到所有节点的最短路径;此时注意维护vector数组vector<int> pre[510],其中每一个vector标志了当前结点之前的所有最短前驱结点;

  1. 调用dfs算法,从需要调整的结点开始(不是从根节点自行车管理委员会办事处),根据前驱结点的vector pre数组,依次向前dfs,并一路上记录need和back,根据need 和back的大小,每次在到达自行车管理处时都比较一次,如果当前更小,则更新path

示意图:

当所有访问到根节点的路径被遍历后,仿真结束。

1021.

Deepest Root

判断图是否是一颗树,如果是树的话,找出最深的根

这里采用了建立vector元素类型的vector方法:

vector<vector<int>> v;

调用v[a].push_back(b);v[b].push_back(a);将图描述。

  1. 在for循环中循环调用dfs

得到的temp就是当使用一个结点时,得到的最深的根的vector,将它们存放到set中,cnt为联通分量的计数。

  1. dfs看上去还是比较简单的,每访问一个,标记一个,通过图的vector,循环多次调用dfs

  1. 在进行一次处理,最深的根节点的集合就是,分别以两个节点,做两次dfs,取结果的并集,就是最深根节点的集合。

1034. Head of Gang

输入一系列的人的联系以及边权,统计有多少个黑帮,边权最大的人就是头目

本质上就是连通分量的统计

连通分量的统计方式使用dfs,一个图做了多少次dfs就有多少次连通分量。

注意:在做dfs时,每扫描过一节点,就将该节点设置为已访问过,或者修改邻接矩阵,将邻接矩阵的权重改为0.

小技巧是这里使用了引用,在每个dfs递归函数中都能修改引用的参数。

dfsTrave遍历矩阵,做过多少次dfs就有少个邻接矩阵

1111. Online Map

给出n个节点对之间的时间距离与路程距离,求给定点到目标点之间的最短距离与最短路径

解题思路:

首先建立邻接矩阵,将节点对之间的关系存入邻接矩阵

调用dijkstra算法,求出结点到目标节点之间的最短时间距离;

调用递归函数,根据dispre[]前驱结点数组找出最终的路径,存入dispath中

调用dijkstra算法,求出结点到目标节点之间的最短长度距离;

调用递归函数,根据dispre[]前驱结点数组找出最终的路径,存入dispath中

如何实现dijkstra算法呢?

如果一共有x个节点,那么最外层最多x个循环

初始化dis[x]数组为极大值,起点对应的数组项为0,

for(n 1:x)

找出未访问过的节点中dis最小的;

将该节点设置为已访问;

                   for(n 1:x)

如果经过该节点到达其邻接结点的距离更小,则

将该节点的邻接结点的距离更新,同时更新前驱结点数组。

递归函数根据目标结点一直追到始发点:

 

1127.

习惯声明的是vector<int> data[50],声明一个vector类型的数组,数组大小为50,其中每一个元素是vector类型的;

树的形式可以用tree[50][2]来表示,即共有50个节点,每个结点的0表示左儿子,1表示右儿子;

根据中序和后序建树:

注意:index使用引用传递,实际上index就是结果,最终递归建立一颗完整的树;

这里的index也仅仅是index,应当是1,2,3,4的序号,这个需要是按照后序来的。

广度优先搜索 bfs:

之前考虑过广度优先搜索如何区分不同的熟悉怒,实际上如果在向队列入队的时候就压入的是结构体类型的node,在node的结构体中将depth深度在入队时就进行累加,那么在出对时,自然就能区分出不同的深度。

根据出队的temp.depth存入vector数组类型的result中。

最后逐层打印:

步骤:建tree,tree中包含结点顺序;广度优先搜索得到result;打印

1147.

判断是最大堆还是最小堆,并后续遍历打印:

首先声明全局的vector变量,在scanf得到vector的大小后,调用v.resize(n)调整为n的大小。

在循环中判断m个序列,每个序列在for((n-1)/2)循环中依次判断左,右。

最后调用后续遍历,由于是完全二叉树,只需要递归索引即可,注意是在postOrder左右两颗树后,打印。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值