(CodeForces) D. Police Stations

传送门

题目大意:一个连通图(树型),每个点都是一个城市,有些城市是有警察局的,任何城市都可以到达d距离的警察局,即每个警察局都有一个有效范围d.问你最多可以删除多少条路,使得每个城市依然可以到达警察局。

解题思路:我们可以这样想,既然给了你k个警察局,那当然是每个都要用上才是最优的,每个城市都应该优先选择和它最近的警察局,如果它选择远的,只会多走一些没有必要的路径。所以可以从每个警察局同时开始宽搜,同时标记走过的边,如果图上所有的城市都被标记,那就宽搜结束。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll maxn=3e5+5;
int n,k,d,cnt=0;
bool vis[maxn];
bool edgevis[maxn];
vector<int> added;
struct edge {
	int to;
	int id;
};
vector<edge> ee[maxn];
struct node {
	int p;
	int step;
};
queue<node> q;

void bfs(){
	while(!q.empty()){
		node st=q.front();
		int np=st.p,nstep=st.step;
		q.pop();
		if(nstep>d)	continue;
		for(int i=0;i<(int)ee[np].size();++i){
			edge tt=ee[np][i];
			int nto=tt.to,nid=tt.id;
			if(!vis[nto]){
				vis[nto]=true;
				edgevis[nid]=true;
				++cnt;
				q.push(node{nto,nstep+1});
			}
			
		}
		
	}
	
}
int main() {
	scanf("%d%d%d",&n,&k,&d);
	memset(vis,false,sizeof(vis));
	memset(edgevis,false,sizeof(edgevis));

	int tmp;
	for(int i=1; i<=k; ++i) {
		scanf("%d",&tmp);
		q.push(node{tmp,0});
		vis[tmp]=true;
	}
	int x,y;
	for(int i=1; i<=n-1; ++i) {
		scanf("%d%d",&x,&y);
		ee[x].push_back(edge {y,i});
		ee[y].push_back(edge {x,i});
	}
	bfs();
	cout<<n-1-cnt<<endl;
	for(int i=1; i<=n-1; ++i) {
		if(edgevis[i]==false) {
			cout<<i<<' ';
		}
	}
	cout<<endl;
	return 0; 
}

猜你喜欢

转载自blog.csdn.net/TDD_Master/article/details/84949779