2665 城镇警局(BFS)
n个城镇编号1到n,中间有n-1通道长度都为1公里。
n个城镇共用k个警局,每个警局可以管理d公里以内的城镇治安。给出n个城镇的连接情况以及k个警局所在的城镇,问有多少城镇没有被任何一家警局管理。
样例中只有4号城镇没有被管理。
输入
第1行:3个数n, k, d (2≤n≤10^5, 1≤k≤10^5, 0≤d≤n - 1) 第2行:共k个数,表示警局在哪个城镇pi。(1≤pi≤n) 后面n-1行:每行两个数u v,表示城镇u和城镇v之间存在道路。(1≤u,v≤n),道路编号从1开始。
输出
输出共1行,对应没有被警局管理的城镇数量。
输入样例
7 2 2
1 7
1 2
2 3
3 4
4 5
5 6
6 7
输出样例
1
看到这个题适合距离有关的,一下就想到了BFS,但是你不能每一个点进行一次BFS,即使优化了也不行
这是我一开始的代码。我很傻逼,没有想到更优解
#pragma GCC optimize(2) #include<iostream> #include<algorithm> #include<vector> #include<queue> #include<cstring> using namespace std; const int maxn=5e5+100; struct nod{ int to; int ne; }e[maxn]; int head[maxn]; int n,k,d; int b[maxn]; bool vis[maxn]; int qq[maxn],step[maxn]; int cnt; void add(int u,int v){ e[cnt].to=v; e[cnt].ne=head[u]; head[u]=cnt++; } struct node{ int s; int d; }; void BFS(int x){ queue<node>q; q.push({x,0}); while(!q.empty()){ node p=q.front(); q.pop(); int u=p.s; int dis=p.d; for(int i=head[u];~i;i=e[i].ne){ int v=e[i].to; if(dis+1<=d&&qq[v]>(dis+1)){ vis[v]=true; qq[v]=min(qq[v],dis+1); q.push({v,dis+1}); } } } } int main(){ memset(head,-1,sizeof(head)); scanf("%d%d%d",&n,&k,&d); // for(int i=0 ;i<n*2+20 ;i++) head[i] = -1; for(int i=1;i<=n;i++){ qq[i]=0x3f3f3f3f; } for(int i=1;i<=k;i++){ scanf("%d",&b[i]); vis[b[i]]=1; } int x,y; for(int i=1;i<n;i++){ scanf("%d%d",&x,&y); add(x,y); add(y,x); } for(int i=1;i<=k;i++){ BFS(b[i]); } int ans=0; for(int i=1;i<=n;i++){ if(!vis[i]){ ans++; } } printf("%d",ans); }
我第一开始也想了,就是遍历一边标记了,不用再遍历了,但是这样不行,就是你遍历b[i]后不能保证有比b[i+1]会更小
其实我SB了,就是忘记了BFS的性质,就是你可以一下把所有的b[i]都入队列,这样就可以保证了,因为你第一开始先入队列的一定是最小的,如果遍历到了这个
就不用再遍历了
#include<iostream> #include<algorithm> #include<queue> #include<vector> using namespace std; const int maxn=1e6+100; vector<int>v[maxn]; int dis[maxn]; int n,m,d; int main(){ queue<int>q; int a; cin>>n>>m>>d; d++; while(m--){ cin>>a; dis[a]=1; q.push(a); } int x,y; for(int i=1;i<=n-1;i++){ cin>>x>>y; v[x].push_back(y); v[y].push_back(x); } while(!q.empty()){ int u=q.front(); q.pop(); for(int i=0;i<v[u].size();i++){ int vv=v[u][i]; if(dis[vv]) continue; dis[vv]=dis[u]+1; q.push(vv); } } int ans=0; for(int i=1;i<=n;i++){ if(dis[i]>d){ ans++; } } cout<<ans<<endl; }