Cod sursa(job #180360)

Utilizator tm_raduToma Radu tm_radu Data 16 aprilie 2008 22:00:18
Problema Salvare Scor 50
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.9 kb
#include <stdio.h>
#define NM 1005

int n, m, i, j, k, opt = NM, kk, nr, p;
int dd[NM], d[NM], t[NM], x[NM], c[NM];
int sol[NM], s, e;
typedef struct nod {
    int vf, s;
    nod* urm;
} NOD, *PNOD;
PNOD l[NM];

void Add(int i, int j);
void Cbin(int st, int dr);
int Ok(int dist);
void Solve();

int main()
{
    freopen("salvare.in", "r", stdin);
    freopen("salvare.out", "w", stdout);
    scanf("%d %d", &n, &kk);
    for ( k = 1; k < n; k++ )
    {
        scanf("%d %d", &i, &j);
        dd[i]++, dd[j]++;
        Add(i, j);
        Add(j, i);
    }
    Cbin(1, n);   // cautam valoarea optima

	p = kk;
	for ( i = 1; i <= n ; i++ )
	    p -= sol[i];     // p - numarul de puncte de salvare gasite
    for ( i = 1; i <= n; i++ )
        if ( p > 0 && sol[i] == 0 )   // punem puncte de salvare pana cand p = kk
        {
            sol[i] = 1;
            p--;
        }
    if ( kk == n ) opt = 0;

    printf("%d\n", opt);
    for ( i = 1; i <= n; i++ )
        if ( sol[i] ) printf("%d ", i);
    printf("\n");
    
    return 0;
}

void Add(int i, int j)
{
    PNOD q = new NOD;
    q->vf = j;
    q->s = 0;
    q->urm = l[i];
    l[i] = q;
}
    
void Cbin(int st, int dr)
{
    if ( st == dr ) return;
    int mij = (st+dr)/2;
    if ( Ok(mij) ) Cbin(st, mij);
    else           Cbin(mij+1, dr);
}

int Ok(int dist)
{
	for ( i = 1; i <= n; i++ )
		c[i] = x[i] = 0, t[i] = 9999, d[i] = dd[i];   // t[i] = distanta de la i pana la cel mai indepartat
													  // punct de salvare
	for ( i = 1; i <= n; i++ )
		for ( PNOD q = l[i]; q; q = q->urm ) q->s = 0;
	nr = 0;
	s = 1, e = 0;
	for ( i = 1; i <= n; i++ )    // introducem in coada frunzele
		if ( d[i] == 1 )
		{
			e++;
			c[e] = i, t[i] = dist;
		}
	while ( s <= e )  // cat timp mai am noduri in graf
	{
		i = c[s];
		PNOD q;
		for ( q = l[i]; q; q = q->urm )  // aleg k = "tatal" lui i
			if ( !q->s )
			{
				q->s = 1;
				k = q->vf;
				break;
			}
		d[i]--, d[k]--;    // sterg muchia
		for ( q = l[k]; q; q = q->urm )   // o sterg din lista de vecini a lui k
			if ( q->vf == i )
			{
				q->s = 1;
				break;
			}
		if ( t[i] < t[k] ) t[k] = t[i];  // daca distanta maxima din i pana la punctul de salvare
										 // este mai mica decat cea din k, actualizam
		if ( d[k] == 1 )    // in cazul in care k devine frunza
		{
			t[k]--;     // ii scadem costul
			if ( t[k] == 0 )   // daca este punct de salvare
			{
				x[k] = 1;
				t[k] = 9999;
				nr++;
			}
			e++;   // il bagam in coada
			c[e] = k;
		}
		s++;
	}
	if ( !nr )    // in cazul in care nu am gasit puncte de salvare, punem unul in ultimul nod sters
		nr = 1, x[c[e]] = 1;

	if ( nr <= kk )  // daca am gasit o solutie valida
	{
		if ( dist < opt )   // actualizam minimul
		{
			opt = dist;
			for ( i = 1; i <= n; i++ ) sol[i] = x[i];  // si copiem solutia
		}
		return 1;
	}
	return 0;
}