news 2026/4/16 12:56:29

刷题日记day4(搜索)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
刷题日记day4(搜索)

第一篇题解

蒟蒻的第四篇题解希望大家支持

题目描述
  • P3915树的分解

P3915 树的分解

题目描述

给出N NN个点的树和K KK,问能否把树划分成N K \frac{N}{K}KN个连通块,且每个连通块的点数都是K KK

输入格式

第一行,一个整数T TT,表示数据组数。接下来T TT组数据,对于每组数据:

第一行,两个整数N , K N, KN,K

接下来N − 1 N - 1N1行,每行两个整数A i , B i A_i, B_iAi,Bi,表示边( A i , B i ) (A_i, B_i)(Ai,Bi)。点用1 , 2 , … , N 1, 2, \ldots, N1,2,,N编号。

输出格式

对于每组数据,输出YESNO

输入输出样例 #1

输入 #1

2 4 2 1 2 2 3 3 4 4 2 1 2 1 3 1 4

输出 #1

YES NO

说明/提示

  • 对于60 % 60 \%60%的数据,1 ≤ N , K ≤ 1 0 3 1 \le N, K \le 10^31N,K103
  • 对于100 % 100 \%100%的数据,1 ≤ T ≤ 10 1 \le T \le 101T101 ≤ N , K ≤ 1 0 5 1 \le N ,K \le 10^51N,K105
思路分析

这是一道有关于树的遍历的题目,和树相关的题目我们一般采用递归实现。在树当中联通块的意思其实就是包括某一个根节点和其所有子节点的一棵子树,这题我们就是要将一整棵树一片片地分解开来,以某一个节点为根节点进行分析,会遇到一下这三种情况1.以该节点为根节点的子树所包括的总节点数小于k2.以该节点为根节点的子树所包括的节点总数等于k3.以该节点为根节点的总结点数大于k,接下来我们分别分析这三种情况该如何处理

  • 1.总节点数不足k个,那么就把这个部分子树并到该根节点的父节点上,返回总节点数
  • 2.总节点数刚好为k,那么这个部分作为一个连通块直接划掉即可,返回0
  • 3.总节点数大于k,说明这个一整棵子树无法分成N/K个联通块,返回-1,即输出一个标记失败情况的数字
可能出现的疑惑

不知道有同学是否会这样想,以该节点为根节点的总节点个数大于k为什么就能判断整棵数不能分成N/K个联通块呢,为什么不能把部分节点分给其他子树呢
有这个疑惑的同学,认真思考了这个问题,现在做出解答。
因为我们看问题的方式太片面了,我们想一想为什么这个以这个节点为根节点的总节点数会大于k呢,那当然是因为该节点的叶子节点返回了过多的点,这看上去是一句废话,但要好好理解一个通俗的解释方式,该节点的叶子节点解决不了自己的问题,就去向该节点寻求帮助,但是寻求帮助以后,该节点就无法解决自身的问题(因为总节点数超过k),对于叶子节点来说他自己解决不了问题(数量不足k个),向上寻求帮助也解决不了问题,那么这个节点的问题无论如何也解决不了(即无论如何也不能凑出k个节点)
给出一个案例

假设我们的目标k是4,绿色框内的每一个叶子节点都不能满足4,只能加到父节点,但是这四个点都加入父节点以后,紫色框内节点总数就超过4,这说明整棵数是不能分成N/4个联通块的

代码展示
#include<iostream>#include<algorithm>#include<cstring>#include<vector>usingnamespacestd;constintN=101000;intT,n,k;vector<int>branch[N];intdfs(intu,intlast){intans=1;//本身就是一个节点for(inti=0;i<branch[u].size();i++){intnext=branch[u][i];if(next==last)continue;intcnt=dfs(next,u);//看看叶子节点的总节点数if(cnt==-1)return-1;if(cnt==k)cnt=0;ans+=cnt;if(ans>k)return-1;}returnans;}intmain(){cin>>T;while(T--){cin>>n>>k;for(inti=1;i<=n;i++)branch[i].clear();//多测,每组要清理数据intx,y;for(inti=1;i<n;i++){cin>>x>>y;branch[x].push_back(y);branch[y].push_back(x);}intcnt=dfs(1,1);if(cnt==k)cout<<"YES"<<endl;elsecout<<"NO"<<endl;}return0;}
细节讲解

注意多测要清理之前的数据,dfs中for循环内的几个if语句的关系是环环相扣的,要仔细思考

AI详细注释代码
#include<iostream>#include<algorithm>#include<cstring>#include<vector>usingnamespacestd;constintN=101000;intT,n,k;// T:测试用例数 n:节点数 k:目标分组大小vector<int>branch[N];// 邻接表存储树的边(branch[u]存u的所有邻接节点)// 递归DFS:计算以u为根的子树可分组的节点数(last是父节点,避免回走)intdfs(intu,intlast){intans=1;// 初始:当前节点自身算1个// 遍历u的所有邻接节点for(inti=0;i<branch[u].size();i++){intnext=branch[u][i];if(next==last)continue;// 跳过父节点,避免重复遍历intcnt=dfs(next,u);// 递归计算子节点next的子树节点数if(cnt==-1)return-1;// 子树不满足条件,直接返回-1if(cnt==k)cnt=0;// 子树节点数刚好凑够k,分组后清零ans+=cnt;// 累加当前子树的有效节点数if(ans>k)return-1;// 节点数超过k,无法分组,返回-1}returnans;// 返回当前子树累计的节点数}intmain(){cin>>T;while(T--){cin>>n>>k;// 多组测试用例,清空邻接表for(inti=1;i<=n;i++)branch[i].clear();// 输入n-1条树的边,构建邻接表intx,y;for(inti=1;i<n;i++){cin>>x>>y;branch[x].push_back(y);branch[y].push_back(x);}// 从根节点1开始DFS(父节点设为1,避免回走)intcnt=dfs(1,1);// 最终累计节点数等于k则符合条件,否则不符合if(cnt==k)cout<<"YES"<<endl;elsecout<<"NO"<<endl;}return0;}

第二篇题解

题目描述
  • P1144最短路计数

P1144 最短路计数

题目描述

给出一个N NN个顶点M MM条边的无向无权图,顶点编号为1 ∼ N 1\sim N1N。问从顶点1 11开始,到其他每个点的最短路有几条。

输入格式

第一行包含2 22个正整数N , M N,MN,M,为图的顶点数与边数。

接下来M MM行,每行2 22个正整数x , y x,yx,y,表示有一条连接顶点x xx和顶点y yy的边,请注意可能有自环与重边。

输出格式

N NN行,每行一个非负整数,第i ii行输出从顶点1 11到顶点i ii有多少条不同的最短路,由于答案有可能会很大,你只需要输出 $ ans \bmod 100003$ 后的结果即可。如果无法到达顶点i ii则输出0 00

输入输出样例 #1

输入 #1

5 7 1 2 1 3 2 4 3 4 2 3 4 5 4 5

输出 #1

1 1 1 2 4

说明/提示

1 115 55的最短路有4 44条,分别为2 221 → 2 → 4 → 5 1\to 2\to 4\to 512452 221 → 3 → 4 → 5 1\to 3\to 4\to 51345(由于4 → 5 4\to 545的边有2 22条)。

对于20 % 20\%20%的数据,1 ≤ N ≤ 100 1\le N \le 1001N100
对于60 % 60\%60%的数据,1 ≤ N ≤ 1 0 3 1\le N \le 10^31N103
对于100 % 100\%100%的数据,1 ≤ N ≤ 1 0 6 1\le N\le10^61N1061 ≤ M ≤ 2 × 1 0 6 1\le M\le 2\times 10^61M2×106

思路分析

最短路问题采用bfs,注意到题目中有重边和自环,自环不用读入,因为你如果已经走到某个点了,再通过自环走一次,只会增加距离肯定不是最短路,由于统计的是不同的路径,所以重边是需要读入的。通过bfs扩展到的点,此时到达该点的路径一定是最短的,又因为我们初始化的距离为正无穷,所以第一次达到以后就会重新更新距离,这里是继承上一个路径数量,跟dijkstra类似,标记为true以后表明到这个点的最短距离已经找到,(虽然这里是为了不走回头路),而之后再次到达该点且距离跟之前相同的话,需要加上上一个路径的数量

代码展示
#include<iostream>#include<algorithm>#include<cstring>#include<vector>#include<queue>usingnamespacestd;constintN=1e6+10,mod=100003;intn,m;boolst[N];//标记已经走过的点intdist[N],path[N];vector<int>branch[N];voidbfs(){queue<int>q;q.push(1);st[1]=true;dist[1]=0;path[1]=1;while(!q.empty()){intt=q.front();q.pop();for(inti=0;i<branch[t].size();i++){intv=branch[t][i];if(dist[t]+1<dist[v]){dist[v]=dist[t]+1;path[v]=path[t];if(!st[v]){st[v]=true;q.push(v);}}elseif(dist[t]+1==dist[v]){path[v]=(path[v]+path[t])%mod;}elsecontinue;}}}intmain(){ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);cin>>n>>m;while(m--){intx,y;cin>>x>>y;if(x==y)continue;branch[x].push_back(y);branch[y].push_back(x);}memset(dist,0x3f,sizeofdist);bfs();for(inti=1;i<=n;i++)cout<<path[i]<<endl;return0;}
细节讲解

距离刚开始要初始化为正无穷

AI详细注释代码
#include<iostream>#include<algorithm>#include<cstring>#include<vector>#include<queue>usingnamespacestd;constintN=1e6+10,mod=100003;// N:节点最大数量 mod:路径数取模值intn,m;// n:节点数 m:边数boolst[N];// 标记节点是否入过队列intdist[N];// 存储节点到起点1的最短距离intpath[N];// 存储节点到起点1的最短路径数量vector<int>branch[N];// 邻接表存储图的边// BFS求解最短距离和最短路径数voidbfs(){queue<int>q;q.push(1);// 起点1入队st[1]=true;// 标记起点已入队dist[1]=0;// 起点到自身距离为0path[1]=1;// 起点到自身路径数为1while(!q.empty()){intt=q.front();// 取出队头节点q.pop();// 遍历当前节点的所有邻接节点for(inti=0;i<branch[t].size();i++){intv=branch[t][i];// 邻接节点v// 情况1:找到更短的路径if(dist[t]+1<dist[v]){dist[v]=dist[t]+1;// 更新最短距离path[v]=path[t];// 更新路径数(继承父节点)if(!st[v]){// 未入队则标记并入队st[v]=true;q.push(v);}}// 情况2:找到等长的最短路径elseif(dist[t]+1==dist[v]){path[v]=(path[v]+path[t])%mod;// 累加路径数并取模}// 情况3:路径更长,直接跳过elsecontinue;}}}intmain(){ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);// 加速输入输出cin>>n>>m;// 输入m条边,构建无向图邻接表while(m--){intx,y;cin>>x>>y;if(x==y)continue;// 跳过自环边branch[x].push_back(y);branch[y].push_back(x);}memset(dist,0x3f,sizeofdist);// 初始化最短距离为无穷大bfs();// 输出每个节点到起点1的最短路径数for(inti=1;i<=n;i++)cout<<path[i]<<endl;return0;}
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/15 17:20:10

【收藏】GPT-5.2来袭!OpenAI最新最强大模型全解析,程序员必学

OpenAI为应对谷歌Gemini系列竞争压力&#xff0c;发布迄今最强大的GPT-5.2模型&#xff0c;包含Instant、Thinking和Pro三个版本&#xff0c;性能较前代有巨大提升。API、Codex已更新&#xff0c;Cursor等第三方工具已支持。作者已将OpenAI产品切换至GPT-5.2&#xff0c;并计划…

作者头像 李华
网站建设 2026/4/16 13:54:24

【必读收藏】2025年扩散模型全领域变革:从架构到应用的深度解析

2025年扩散模型正经历从U-Net到DiT(Transformer)架构的重大转变&#xff0c;引发可控生成、图像编辑和主体定制化等领域的创新与挑战。ControlNet面临算力瓶颈&#xff0c;OmniControl等高效方案兴起&#xff1b;图像编辑向基于指令的方法演进&#xff1b;主体定制化因架构变化…

作者头像 李华
网站建设 2026/4/13 1:24:51

003-RSA魔改:一号店

本文案例网站&#xff1a;一号店 定位加密参数 打开网页输入账号密码&#xff0c;抓包后发现账号密码都加密了&#xff1a; 下面的参数对比发现不变&#xff0c;我们直接搜索关键字&#xff1a; 账号密码都在这里&#xff0c;大概率就在这里前后都打上断点&#xff1a; 断下来…

作者头像 李华
网站建设 2026/4/12 14:25:03

Day 36 官方文档的阅读

浙大疏锦行 官方文档的检索方式&#xff1a;GitHub和官网 官方文档的阅读和使用&#xff1a;要求安装的包和文档为同一个版本 类的关注点&#xff1a; a.实例化所需要的参数 b.普通方法所需要的参数 c.普通方法的返回值 绘图的理解&#xff1a;对底层库的调用 import p…

作者头像 李华
网站建设 2026/4/13 5:11:14

基于协同过滤的旅游酒店和订餐系统设计与实现

基于协同过滤的旅游酒店和订餐系统设计与实现 一.系统概述本系统旨在为用户提供一个智能化的旅游酒店和餐饮推荐平台&#xff0c;结合用户偏好、行为数据以及协同过滤算法&#xff0c;实现个性化的推荐功能。用户可以通过注册登录进行操作&#xff0c;使用该平台搜索和预定酒店…

作者头像 李华