1. 程式人生 > >cf 769 D Police Stations

cf 769 D Police Stations

題目的大意是給你一顆n結點的樹,然你刪除儘可能多的結點仍能讓題目給出的一些樹中特殊標記過的結點滿足任意點距離d內都有特殊結點。

由於是樹,而又要滿足題意,所以k個點最多刪除不能超過k-1條邊,但題目中給的k是可能存在一個結點有相當於多個特殊點,所以是坑點,不能直接用它給的。不要想太多直接bfs搜就對了,如果當前邊沒走過但是到的點走過了,就可以刪除,這樣一遍就可以了,也不會存在什麼問題。

#include<iostream>
#include<string>
#include<algorithm>
#include<vector>
#include<queue>
#define maxn 300100

using namespace std;

struct point{
	int v, id;
	point(int v, int id):v(v), id(id){
	}
	point(){
	}
};

int edge[maxn], vis[maxn];
queue<int> q;
vector<point> v[maxn];

int bfs()
{
	int ans= 0;
	while(!q.empty())
	{
		int u = q.front();
		q.pop();
		for(int i=0; i<v[u].size(); i++)
		{
			point n = v[u][i];
			if(edge[n.id])
				continue;
			if(vis[n.v])
			{
				edge[n.id] = 2;
				ans++;
				continue;
			}
			vis[n.v] = 1;
			edge[n.id] = 1;
			q.push(n.v);
		}
	}
	return ans;
}


int main()
{
	int n, k, d;
	cin>>n>>k>>d;
	int m;
	for(int i=0; i<k; i++)
	{
		scanf("%d", &m);
		vis[m] = 1;
		q.push(m);
	}
	int x, y;
	for(int i=0; i<n-1; i++)
	{
		scanf("%d%d", &x, &y);
		v[x].push_back(point(y,i));
		v[y].push_back(point(x,i));
	}
	cout<<bfs()<<endl;
	for(int i=0; i<n-1; i++)
	{
		if(edge[i] == 2)	
			printf("%d ", i+1);
	}
	cout<<endl;
	return 0;
}