Cod sursa(job #166332)

Utilizator kaesarioDumi Loghin kaesario Data 27 martie 2008 21:00:47
Problema Salvare Scor 30
Compilator c Status done
Runda Arhiva de probleme Marime 3.67 kb
#include <stdio.h>
#include <string.h>
#define MAX 1002

/* variabile globale */
long p,opt,nr,st,en,lo,hi,med,i,j,k,l,m,n,mp;
int dd[MAX],start[MAX],d[MAX],sol[MAX];
long a[2*MAX][2];		/* reprezentare graf */
long ok[2*MAX];
	
int try(){
	int c[MAX], t[MAX],x[MAX], kk;
	
	int try = 0; /* false */
	for (i=0; i<MAX; i++){
		ok[i]=c[i]=x[i]=0;
	}
	// ok = pentru fiecare latura
	// c = coada de varfuri
	// x = salutie partiala
	
	//d=dd;
	memcpy(d, dd, sizeof(dd));
	
	for(i=0;i<n;i++){ 
		t[i]=9999; 					// timp rezolvare
	}
	
	nr=0; 							// nr. puncte salvare
	
	// bag in coada frunzele si trimit in sus  
	st=0; 
	en=-1; 
	for(i=0;i<n;i++)
		if (d[i]==1){ 
			en++; 
			c[en]=i; 
			t[i]=med; 
		}

	while (en<n-1){
	// scade gradul vecinului lui st 
	// daca acesta are gradul 0, il baga in coada 
		i=c[st]; 
		for(j=start[i];j<=start[i+1]-1;j++) 
			if (ok[j]==0){ 
				ok[j]=1; 
				kk=a[j][1]; 
				break; 
			} 
		d[i]--; 
		d[kk]--; 
		if (t[i]<t[kk])
			t[kk]=t[i]; 
		for(j=start[kk];j<=start[kk+1]-1;j++) 
			if (a[j][1]==i){  
				ok[j]=1; 
				break; 
			}
		if (d[kk]==1){ 
			
			t[kk]=t[kk]-1; 
			if (t[kk]==0){ 
				 
				x[kk]=1; 
				t[kk]=2*med+1; 
				nr++; 
				
			}
			en++; 
			c[en]=kk; 
			
		}
		st++; 
	
	}
	
	/* daca nu am fixat niciun punct il fixam pe ultimul din coada */ 
	if (nr==0){  
		nr=1; 
		x[c[en]]=1; 
	}
	/* am gasit solutie */
	if (nr<=k){ 
		try=1; 
		if (med<opt){ 
			opt=med;
			/* sol = solutia partiala */
			memcpy(sol, x, sizeof(x));
		}
	}
	return try;
}

void solve(){
	opt=n+1; // timpul de rezolvare maxim
	m=2*n-2; // 
	/* ordonare crescatoare dupa primul varf */
	for(i=0;i<m;i++){ 
		mp=i; 
		for(j=i+1;j<m;j++) 
			if ((a[j][0]<a[mp][0])||((a[j][0]==a[mp][0])&&(a[j][1]<a[mp][1]))) 
				mp=j; 
		/* interschimb */
		for (j=0; j<2; j++){
			a[m][j]=a[mp][j];
			a[mp][j]=a[i][j]; 
			a[i][j]=a[m][j]; 
			a[m][j]=a[m+1][j]; 
		}
	}
	/*
	for (i=0; i<m; i++){
		printf("%ld %ld\n", a[i][0], a[i][1]);
	}
	*/
	/* se determina:
	 * 	- start[i] = prima muchie care are nod de plecare i
	 * 	- d[i] = gradul nodului i 
	 */
	start[0]=0; 
	j=0; 
	for(i=1;i<n;i++){ 
		do{
			j++;
		}while(a[j][0]!=i); 
		start[i]=j; 
	}
	start[n]=m; 
	for(i=0;i<n;i++) 
		d[i]=start[i+1]-start[i]; 
	/* salveaza d */
	for (i=0; i<n; i++)
		dd[i] = d[i];
	/*
		for (i=0; i<n; i++)
			printf("%ld ", d[i]);
	*/
	/* urmeaza cautarea binara */
	
	lo=1; 
	hi=n; 
	while(lo<=hi){ 
		//begin 
		med=(lo+hi) / 2; 
		if (try()) 
			hi=med-1; 
		else 
			lo=med+1; 
		//end;
	}
	p=k;		// k = nr. de posturi salvare 
	/* cate posturi de salvare avem ? */
	for(i=0;i<n;i++) 
		p=p-sol[i];
	/* daca nu sunt k posturi, se completeaza pana la k in ordine crescatoare */
	for(i=0;i<n;i++) 
		if ((p>0) && (sol[i]==0)){
			//begin 
			sol[i]=1; 
			p--;	
			//end;
		}
	if (k==n)		/* caz particular - ar trebui tratat mai devreme */
		opt=0; 
}

int main(){
	/* variabile */
	FILE *f;
	char fin[15] = "salvare.in", fout[15] = "salvare.out";
	
	/* citire date */
	f = fopen(fin, "rt");
	if (!f){
		printf("Eroare fisier intrare!\n");
		return -1;
	}
	fscanf(f, "%ld %ld", &n, &k);
	for (i=0; i<n-1; i++){
		fscanf(f, "%ld %ld", &a[i][0], &a[i][1]);
		a[i][0]--;	// pt reprezentare interna
		a[i][1]--;
		a[n-1+i][0]=a[i][1]; 
		a[n-1+i][1]=a[i][0]; 
	}
	fclose(f);
	/* algoritm */
	solve();
	/* afisare date */
	f = fopen(fout, "wt");
	fprintf(f,"%ld\n", opt);	/* maximum timpilor de rezolvare */
		for(i=0;i<n;i++) 
			if (sol[i]==1) 
				fprintf(f, "%ld ",i+1); /* punctele de salvare */
	fprintf(f,"\n");
	fclose(f);
	return 0;
}