题意 : 给你n个点,给你m个警察局,每个警察局有一个控制范围k,让你删除尽量多的边使得,每个点都可以被警察局控制。
题解 : 这个题我们要考虑哪些类型的边可以被删掉,就是那些被两个警察局同时控制的边,这种边是什么样的呢 ? 就是说这条边的两个点分别被两个警察局控制,这样的边就可以删掉,我们怎样找这样的边呢 ? 我们就可以开始的时候将所有的警察局的点都扔进队列,做bfs 这样的将访问的边和点都打上标记,当 距离大于控制范围时不再入队列,当访问到某条边,这条边没有被访问过并且两个端点都被访问的时候,这条边就是可以删除的边,把这条边认为已经访问过即可。
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <queue>
using namespace std;
const int maxn = 3e5 + 10;
queue <int> q;
struct node {
int to;
int id;
};
vector <node> G[maxn];
bool vis[maxn] = {0};
bool ed[maxn] = {0};
int res[maxn] = {0};
int d[maxn] = {0};
int main () {
ios_base :: sync_with_stdio(false);
int n,m,mx;
cin >> n >> m >> mx;
for (int i = 1;i <= n; ++ i) {
d[i] = 1000000007;
}
for (int i = 0;i < m; ++ i) {
int x;
cin >> x;
q.push(x);
d[x] = 0;
vis[x] = 1;
}
for (int i = 1;i <= n - 1; ++ i) {
int x,y;
cin >> x >> y;
G[x].push_back ({y,i});
G[y].push_back ({x,i});
}
int cnt = 0;
while (!q.empty()) {
int u = q.front();
q.pop();
int k = G[u].size();
for (int i = 0;i < k; ++ i) {
int v = G[u][i].to;
if (!vis[v]) {
d[v] = min (d[v],d[u] + 1);
if (d[v] > mx) continue;
vis[v] = 1;
q.push(v);
int id = G[u][i].id;
ed[id] = 1;
}
else if (!ed[G[u][i].id]) {
int id = G[u][i].id;
ed[id] = 1;
res[cnt ++] = id;
}
}
}
cout << cnt << endl;
for (int i = 0;i < cnt; ++ i) {
cout << res[i] << ' ';
}
cout << endl;
return 0;
}