生化危机(来自qduoj)
题目链接
题目大意
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的父亲节点了,后来才发现要标记一下才行。


