Cod sursa(job #168693)

Utilizator sanaDascalu Laurentiu sana Data 31 martie 2008 18:51:46
Problema Salvare Scor 0
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.34 kb
#include <fstream>  
#include <vector>
#include <queue>
#include <iostream>

using namespace std;

#define FILEIN "salvare.in"  
#define FILEOUT "salvare.out"  
#define MAX(A,B) ((A)>(B)?(A):(B))  
#define INF 10000000

void dfs(int i, vector<vector <int> > &data, vector<int> &cost,
		vector<int> &taken, vector<int> &visited, int &dist, int &nr_pa,
		int cost);

void mysearch(vector<vector <int> > &data, vector<int> &cost,
		vector<int> &taken, vector<int> &visited, int &dist, int &nr_pa) {
//	cout << "Pentru distanta " << dist << endl;
	for (int i=1; i<(int)data.size(); i++) {
		if (data[i].size()==1) {
//			cout <<"Intru in " << i << endl;
			dfs(i, data, cost, taken, visited, dist, nr_pa, 0);
		}
	}
}

void dfs(int node, vector<vector <int> > &data, vector<int> &cost,
		vector<int> &taken, vector<int> &visited, int &dist, int &nr_pa, int C) {
	int next;
	// Daca nodul a fost vizitat.
	if (visited[node]) {
//		cout << "Vizitat deja " << node << endl;
		return;
	}
//	cout << "Vizitez pe " << node << endl;
	visited[node]=1;
	next=data[node][0];
	cost[node]=C;
//	cout << "Costul este " << C << endl;
	if (C==dist) {
//		cout << "Pun un punct de salvare " << node << endl;
		nr_pa++;
		taken[node]=1;
		C=0;
	}
//	cout << "Trec la " << next << endl;
	dfs(next, data, cost, taken, visited, dist, nr_pa, C+1);
}

int main() {
	int N, K;
	int inf, sup, dist, nr_pa;
	vector<vector <int> > data;
	vector<int> visited, cost, taken;
	ifstream fin(FILEIN,ios::in);
	ofstream fout(FILEOUT,ios::out);

	fin >> N >> K;
	for (int i=0; i<=N; i++) {
		data.push_back(vector<int>());
		visited.push_back(0);
		taken.push_back(0);
		cost.push_back(0);
	}

	for (int i=1; i<N; i++) {

		fin >> inf >> sup;
		data[inf].push_back(sup);
		data[sup].push_back(inf);
	}

	fin.close();
	/*	
	 for (int i=1;i<(int)data.size();i++) {
	 fout << i << " ";
	 for (int j=0;j<(int)data[i].size();j++) {
	 fout << data[i][j] << " ";
	 }
	 fout << endl;
	 }
	 */
	// Daca numarul de puncte de salvare este mai mare decat numarul de cabane
	// atunci infiintam in fiecare nod cate un punct de salvare.
	if (K>=N) {
		fout << 0 << endl;
		for (int i=1; i<=N; i++)
			fout << i << " ";
		fout.close();
		return 0;
	}

	// Evident ca numarul de puncte de ajutor este invers proportional
	// cu distanta minima ceruta. Cu cat crestem numarul de puncte de ajutor
	// cu atat distanta scade.

	inf=1;
	sup=N;
	dist=(inf+sup)/2;

	// Pentru o anumita distanta D calculez numarul de puncte de ajutor
	// necesare acoperirii arborelui.
	while (inf!=sup && inf!=dist) {
		// Initial, numarul de puncte de ajutor este 0 si distanta o caut binar.
		nr_pa=0;
		dist=(inf+sup)/2;

		// Initializez fiecare nod al arborelui : nevizitat, cost infinit si neacoperit
		// de vreun punct de salvare.
		for (int i=1; i<=N; i++) {
			visited[i]=0;
			cost[i]=INF;
			taken[i]=-1;
		}

		mysearch(data, cost, taken, visited, dist, nr_pa);

		// Daca numarul de puncte de ajutor este mai mare decat numarul limita
		// dat atunci distanta trebuie crescuta.
		if (nr_pa>K)
			inf=dist+1;
		else
			sup=dist;
	}

	fout << dist << endl;
	int count=0;
	for (int i=1; i<=N; i++) {
		if (taken[i]==1) {
			fout << i << " ";
			count++;
		}
	}

	if (count<K) {
		for (int i=1; i<=N; i++) {
			if (taken[i]!=1) {
				fout << i << " ";
				count++;
				if (count==K)
					break;
			}
		}
	}

	fout.close();
	return 0;
}

// Astfel se obtine o complexitate de O(N*logN).