Cod sursa(job #834842)

Utilizator vendettaSalajan Razvan vendetta Data 15 decembrie 2012 14:22:37
Problema Salvare Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.46 kb
#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>
#include <set>
#include <queue>
#include <deque>

using namespace std;

ifstream f("salvare.in");
ofstream g("salvare.out");

#define nmax 1005
#define ll long long

int n, K, t[nmax], vindecat[nmax], aux[nmax], rez[nmax], nivel[nmax];
bool spital[nmax], viz[nmax];
vector<int> gf[nmax];

void citeste(){

	f >> n;
	f >> K;
	for(int i=1; i<n; ++i){
        int x, y;
        f >> x >> y;
        gf[x].push_back(y);
        gf[y].push_back(x);
	}

}

void dfs(int nod){

    viz[nod] =1;
    for(int i=0; i<gf[nod].size(); ++i){
        int vc = gf[nod][i];
        if (viz[vc] == 1) continue;
        nivel[vc] = nivel[nod] - 1;
        t[vc] = nod;
        dfs(vc);
    }

}

int afla_tata(int nod, int val){

    int cnt = 0;
    for(; t[nod]!=0 && cnt<val; ++cnt, nod=t[nod]);
    return nod;

}

void baga_dfs(int nod, int x){

    if (x <= 0) return;// daca nuami pot ajuta
    vindecat[nod] = x;
    for(int i=0; i<gf[nod].size(); ++i){
        int vc = gf[nod][i];
        if (vindecat[vc] < x - 1){//daca vecinul era ajuta de un spital care se afla mai departe decat asta de acum
            // il iau pe asta pt ca exista sansa sa mai vindec ceva noduri pe care nu le-am vindetcat cu spitalul precedent
            baga_dfs(vc, x-1);
        }
    }

}

inline bool tot(){

    int ok =1;
    for(int i=1; i<=n; ++i)
        if (vindecat[i] <= 0){
            ok = 0;
            break;
        }

    return ok;

}


void init(){

    for(int i=1; i<=n; ++i) vindecat[i] = 0, spital[i] = 0;

}

inline bool pot(int T){

    init();

    int cnt = 0;
    for(int i=1; i<=n; ++i){
        int nod = aux[i];
        if (vindecat[nod] > 0) continue;
        int tata = afla_tata(nod, T);
        //acum bag un dfs din acest nod; evident daca nu e vindecat;
        //cout << tata << "\n";
        //bag aici un spital
        ++cnt;
        spital[tata] = 1;
        baga_dfs(tata, T+1);
    }
    //cout << cnt << "\n";
    if (cnt <= K ) return 1;
    return 0;

}

struct cmp{

    bool operator() (const int &a, const int &b){
        if( nivel[a] < nivel[b]) return 1;
        return 0;
    }

};

void rezolva(){

    // caut binar raspunsul; apoi pentru un T fixat pornesc din frunze si tot bag spitale la distante T fata de nodul la care ma aflu;
    // fie ca ma aflu in nodul X; ii iau al Tlea tata si din acest nod marhez toate nodurile la care pot ajunge intr-un timp T;
    // vin de jos in sus pe arbore ;
    dfs(1);
    for(int i=1; i<=n; ++i) aux[i] = i;
    sort(aux+1, aux+n+1, cmp() );
    //cout <<pot(2);

    int st = 0;
    int dr = nmax;
    while(dr - st>1){
        int mij = (st + dr) / 2;
        if ( pot(mij) == 1 ){
            //cout << dr << '\n';
            dr = mij;
            for(int i=1; i<=n; ++i){
                rez[i] = spital[i];
            }

        }else st = mij;
    }

    //cout << dr << "\n";
    g << dr << "\n";

    int cnt =0;
    for(int i=1; i<=n; ++i){
        viz[i] = rez[i];
        if (viz[i] ==1) ++cnt;
    }
    if (cnt < K){
        for(int j=1; j<=n && cnt <K; ++j){
            if (viz[j] == 0){
                ++cnt;
                viz[j] = 1;
            }
        }
    }
    for(int i=1; i<=n; ++i){
        if (viz[i] == 1) g << i << " ";
    }

}

int main(){

    citeste();
    rezolva();

    f.close();
    g.close();

    return 0;

}