CF796D Police Stations(bfs+思维)

本题首先告诉我们,初始的树是符合条件的

我们考虑如何构造出一种正确答案。

如果一个边可以删除,说明这个边的两端点在删除边之后仍然能够满足题目的要求,因此我们可以看出,在理想的情况下,最多也只能删除k-1条边

因为我们至多只能有k个孤立集合,前提是每个集合里面都有一个警察局。

发现了这个点之后,可以感觉出来这是一种由每个警察局覆盖出去的做法。

因此考虑用bfs染色每个点,这样如果一个边的两端点颜色不同,这个边就能删除。

同时这也是正确的解法,因为我们每次删边都是分出了一个满足题意的集合。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pll;
const int N=6e5+10;
const int inf=0x3f3f3f3f;
int h[N],ne[N],e[N],idx;
void add(int a,int b){
    e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
int n,k,d;
int from[N],to[N];
struct node{
    int id,col;
};
queue<node> q;
int st[N];
int pos[N];
int ans[N];
void bfs(){
    while(q.size()){
        auto t=q.front();
        q.pop();
        for(int i=h[t.id];i!=-1;i=ne[i]){
            int j=e[i];
            if(st[j])
                continue;
            st[j]=1;
            pos[j]=t.col;
            q.push({j,t.col});
        }
    }
}
int main(){
    ios::sync_with_stdio(false);
    memset(h,-1,sizeof h);
    int i;
    cin>>n>>k>>d;
    for(i=1;i<=k;i++){
        int x;
        cin>>x;
        if(st[x])
            continue;
        q.push({x,i});
        st[x]=1;
        pos[x]=i;
    }
    for(i=1;i<n;i++){
        cin>>from[i]>>to[i];
        add(from[i],to[i]);
        add(to[i],from[i]);
    }
    bfs();
    int cnt=0;
    for(i=1;i<n;i++){
        if(pos[from[i]]!=pos[to[i]]){
            ans[++cnt]=i;
        }
    }
    cout<<cnt<<endl;
    for(i=1;i<=cnt;i++){
        cout<<ans[i]<<" ";
    }
    cout<<endl;
}
View Code

 

posted @ 2020-10-16 11:42  朝暮不思  阅读(119)  评论(0编辑  收藏  举报