![[GESP202503 六级] 树上漫步(含视频)](http://pic.xiahunao.cn/yaotu/[GESP202503 六级] 树上漫步(含视频))
视频讲解[GESP202503 六级] 树上漫步-信息学奥赛GESP等级考试真题解析一、原题题目描述小 A 有一棵 n 个结点的树这些结点依次以 1,2,⋯,n 标号。小 A 想在这棵树上漫步。具体来说小 A 会从树上的某个结点出发每一步可以移动到与当前结点相邻的结点并且小 A 只会在偶数步可以是零步后结束漫步。现在小 A 想知道对于树上的每个结点从这个结点出发开始漫步经过偶数步能结束漫步的结点有多少个可以经过重复的节点。输入格式第一行一个正整数 n。接下来 n−1 行每行两个整数 ui,vi表示树上有⼀条连接结点 ui 和结点 vi 的边。输出格式一行n 个整数。第 i 个整数表示从结点 i 出发开始漫步能结束漫步的结点数量。输入输出样例输入 #13 1 3 2 3输出 #12 2 1输入 #24 1 3 3 2 4 3输出 #23 3 1 3说明/提示对于 40% 的测试点保证 1≤n≤10^3。对于所有测试点保证 1≤n≤2×10^5。二、做题思路1)填充数据#includebits/stdc.h using namespace std; mapint,vectorintg; int main(){ //1)填充数据 //1.1)确定节点数量n int n;cinn; //1.2)填充n-1条边的链接情况 for(int i1;in-1;i){ int u,v;cinuv; g[u].push_back(v); g[v].push_back(u); } return 0; }2)深搜计算奇/偶数高度的节点数量#includebits/stdc.h using namespace std; mapint,vectorintg; bool vis[200005]; int d[200005]; int total[2]; //2.2)深搜每个结点 void dfs(int x,int deep){ //2.4)计算奇数偶数结点数量 total[deep%2]; //2.5)标记当前结点的高度 d[x]deep; vis[x]1; for(auto it:g[x]){ if(vis[it]0){ //2.3)计算当前结点高度 dfs(it,deep1); } } } int main(){ //1)填充数据 //... //2)深搜计算奇/偶数高度的节点数量 //2.1)从结点1开始深搜 dfs(1,1); return 0; }3)输出结果#includebits/stdc.h using namespace std; mapint,vectorintg; bool vis[200005]; int d[200005]; int total[2]; //2.2)深搜每个结点 void dfs(int x,int deep){ //2.4)计算奇数偶数结点数量 //.... //2.5)标记当前结点的高度 //... //2.3)计算当前结点高度 //... } int main(){ //1)填充数据 //... //2)深搜计算奇/偶数高度的节点数量 //2.1)从结点1开始深搜 dfs(1,1); //3)输出结果 for(int i1;in;i){ //结点高度是奇数输出奇数总数 if(d[i]%21) couttotal[1] ; //结点高度是偶数输出奇数偶数 else couttotal[0] ; } return 0; }三、答案#includebits/stdc.h using namespace std; mapint,vectorintg; bool vis[200005]; int d[200005]; int total[2]; //2.2)深搜每个结点 void dfs(int x,int deep){ //2.4)计算奇数偶数结点数量 total[deep%2]; //2.5)标记当前结点的高度 d[x]deep; vis[x]1; for(auto it:g[x]){ if(vis[it]0){ //2.3)计算当前结点高度 dfs(it,deep1); } } } int main(){ //1)填充数据 //1.1)确定节点数量n int n;cinn; //1.2)填充n-1条边的链接情况 for(int i1;in-1;i){ int u,v;cinuv; g[u].push_back(v); g[v].push_back(u); } //2)深搜计算奇/偶数高度的节点数量 //2.1)从结点1开始深搜 dfs(1,1); //3)输出结果 for(int i1;in;i){ //结点高度是奇数输出奇数总数 if(d[i]%21) couttotal[1] ; //结点高度是偶数输出奇数偶数 else couttotal[0] ; } return 0; }