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; }
没有人不辛苦,只有人不喊疼