1. 程式人生 > >(CodeForces) D. Police Stations

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