题目链接
题目大意
n个节点的一棵树,先确定一个节点,问与其直接相连的节点的个数,与其隔一个节点相连的节点的个数,与其隔两个节点相连节点的个数……;
输入:t组数据;每组数据n,k分别代表n个城市,k是基准城市序号;n-1行道路,输入u,v,相连城市的序号。
输出:每组数据的第一行先输出全部城市被遍历需要几次,再以此输出每天遍历的城市个数。
解题思路
一眼过去直接bfs。
加个统计就行,其实这个统计也不是特别好想。
还是讲讲代码吧。
AC代码
#include<bits/stdc++.h> using namespace std; const int N=1e4+5; int ans[N]={1};//用来存储每天被感染的城市数,ans[0]表示第一天被感染的城市数……,初始化第一天为1 vector<int> a[N];//存城市之间的道路 int vis[N];//标记数组 int bfs(int x){ int cnt=0,t=1,Time=0; //这几个变量不好理解, //cnt用于统计某天被感染城市总数,会不断刷新; //判断Time是否与昨天被感染的城市数相等,若相等了,说明cnt已经统计完成,把所以当日被感染的城市都统计上了。本质上是判断是否父亲节点全部遍历完成。 //t用于控制ans数组的索引 queue<int> q;//bfs所用队列 q.push(x); while(!q.empty()){ int tmp=q.front(); q.pop(); Time++; for(int i=0;i<a[tmp].size();i++){ int id=a[tmp][i];//与tmp节点相连的节点 if(vis[id]) continue;//若与tmp节点相连的节点被访问过,continue cnt++;//统计 q.push(id); vis[id]=1; //cout<<id<<endl; } if(Time==ans[t-1]) ans[t++]=cnt,Time=0,cnt=0;//若父亲节点遍历完了,cnt、Time置零,并给ans赋值。 } return t-1; } int main(){ int t,n,k; cin>>t; while(t--){ memset(vis,0,sizeof vis);//注意清空 cin>>n>>k; vis[k]=1;//注意先标记一下基准节点 for(int i=1;i<n;i++){ int u,v; cin>>u>>v; a[u].push_back(v); a[v].push_back(u); } int res; cout<<(res=bfs(k))<<endl; for(int i=0;i<res;i++) cout<<ans[i]<<' '; cout<<endl; //注意清空 for(int i=0;i<=n;i++) a[i].clear(); } }
总结
还好,debug了一会,错以为tmp就是tmp的父亲节点了,后来才发现要标记一下才行。