Cod sursa(job #1659121)

Utilizator tamionvTamio Vesa Nakajima tamionv Data 21 martie 2016 23:50:27
Problema Salvare Scor 60
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.18 kb
#include <fstream>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <cmath>
using namespace std;

int min_nr_pt_dist(const vector<vector<int>>& v, const int dist, vector<int>& tmp){
	const int n = v.size();
	vector<int> grad(n), xor_sum(n, 0), com(n, 3*dist), other_com(n, -1);

	for(int i = 0; i < n; ++i){
		grad[i] = v[i].size();
		for(const auto x : v[i]){
			xor_sum[i] ^= x; } }

	queue<int> de_viz;
	for(int i = 0; i < n; ++i){
		if(grad[i] <= 1){
			de_viz.push(i);
			com[i] = dist; } }

	int rez = 0;
	while(!de_viz.empty()){
		const int cur = de_viz.front();
		de_viz.pop();

		if(grad[cur] == 0){
			int close = -1, far = 2*n+2;
			for(const auto x : v[cur]){
				close = max(close, other_com[x]);
				far = min(far, com[x]); }
			close = 2*dist+2 - close, far = 2*dist+2 - far;
			if(close + far > 2*dist+1){
				++rez;
				tmp.push_back(cur); }
			break; }
		
		const int tata = xor_sum[cur];

		--grad[tata];
		if(grad[tata] <= 1){
			de_viz.push(tata); }

		xor_sum[tata] ^= cur;

		if(com[cur] == 0){
			++rez;
			tmp.push_back(cur);
			com[cur] = 2*dist+1;
			other_com[cur] = 2*dist + 1; }

		com[tata] = min(com[tata], com[cur]-1);
		other_com[tata] = max(other_com[tata], other_com[cur]-1); }


	return rez; }

template <typename F>
int cbin(const int st, int dr, F f){
	for(int step = 1<<(int)log2(dr-st+1); step; step /= 2){
		if(dr-step >= st && f(dr-step)){
			dr -= step; } }
	return dr; }

int main(){
	ifstream f("salvare.in");
	ofstream g("salvare.out");
	int n, k;
	f >> n >> k;

	if(n == 1){
		g << 1 << '\n' << 1;
		return 0; }

	vector<vector<int>> v(n);

	for(int i = n-1, a, b; i > 0; --i){
		f >> a >> b;
		--a, --b;
		v[a].push_back(b);
		v[b].push_back(a); }

	vector<int> rez;

	const int min_dist = cbin(0, n, [&](const int x){
		vector<int> tmp;
		if(min_nr_pt_dist(v, x, tmp) <= k){
			rez = tmp;
			return true; }
		return false; });

	vector<bool> e_luat(n, false);

	for(const auto x : rez){
		e_luat[x] = true; }

	for(int i = n-1, luate = rez.size(); i >= 0 && luate < k; --i){
		if(!e_luat[i]){
			rez.push_back(i);
			++luate; } }

	g << min_dist << endl;

	sort(begin(rez), end(rez));
	for(const auto x : rez){
		g << x+1 << ' '; }

	return 0; }