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;
}

 

 
posted @ 2021-05-08 00:44  lipu123  阅读(294)  评论(0)    收藏  举报