Cod sursa(job #744196)

Utilizator Marius_mFMI-M2 Marius Melemciuc Marius_m Data 7 mai 2012 23:28:52
Problema Arbore partial de cost minim Scor 0
Compilator cpp Status done
Runda Arhiva educationala Marime 3.2 kb
#include<cstdio>
#include<iostream>
#include<algorithm>

using namespace std;
int cost[400001];

class GrafOrientat
{
protected:
	int e1[400001],e2[400001];              // muchia i va fi de fapt muchia v1[i] - v2[i],avand costul cost[i]
	int n,m;
	FILE *in,*out;
public:
	GrafOrientat();
	~GrafOrientat();
};

GrafOrientat::GrafOrientat()
{                                                              for(int i=0;i<400000;i++) e1[i]=e2[i]=cost[i]=0;
	in=fopen("apm.in","r");
	out=fopen("apm.out","w");
	fscanf(in,"%d %d",&n,&m); cout<<m;
	for(int i = 1 ; i <= m ; i++)
		fscanf(in,"%d %d %d",&e1[i],&e2[i],&cost[i]);
}

GrafOrientat::~GrafOrientat()
{
	fclose(in);
	fclose(out);
}

class Kruskal : public GrafOrientat
{
	int T[200001],Rang[200001];                                 
	typedef struct muchie { int x,y,cost; }MUCHIE;
	MUCHIE APM[400001];
	int CostAPM,nr_APM,indice[400001];
public:
	Kruskal();            // constructor
	~Kruskal();
	//bool cmp(int,int);
	void MakeSet(int);
	int FindRoot(int);
	void Link(int,int);
	void Unite(int,int);
	void Solve();
	void printAPM();
};

Kruskal::Kruskal()
{                                                            
	CostAPM = 0;                                     for(int i=0;i<200000;i++) T[i]=Rang[i]=0;
	nr_APM = 0;
	for(int i = 1 ; i <= n ; i++ )
	{
		this->MakeSet(i);
		indice[i] = i;
	}
	for(int i = n + 1 ; i <= m ; i++ )
		indice[i] = i;
}

Kruskal::~Kruskal()
{}

bool cmp(int x,int y)
{
	return (cost[x] < cost[y]);
}

inline void Kruskal::MakeSet(int x)
{
	T[x] = x;
	Rang[x] = 1;
}

int Kruskal::FindRoot(int x)
{
	int i,a;
	for( i = x ; T[i] != i ; i = T[i] )        // cand se termina for-ul,i o sa fie radacina/reprezentantul arborelui/set-ului din care face parte x
		;
	while(T[x] != x)                // facem path compresion/compresia drumurilor
	{
		a = T[x];
		T[x] = i;
		x = a;
	}
	return i;
}

void Kruskal::Link(int x,int y)
{
	if(Rang[x] < Rang[y])
		T[x] = y;
	else
		if(Rang[x] > Rang[y])
			T[y] = x;
		else
			if(Rang[x] == Rang[y])
			{
				T[x] = y;
				Rang[y]++;
			}
}

inline void Kruskal::Unite(int x,int y)
{
	Link(this->FindRoot(x),this->FindRoot(y));
}

void Kruskal::Solve()
{
	int i,a,b,CapatMuchie1,CapatMuchie2,CostMuchie;     // CapatMuchie1 - primul varf al muchiei,CapatMuchie2 - al doilea varf al muchiei
	sort(indice + 1,indice + m + 1,cmp);
	for(i = 1 ; i <= m - 1 ; i++ )
	{	
		CapatMuchie1 = e1[indice[i]];
		CapatMuchie2 = e2[indice[i]];
		CostMuchie = cost[indice[i]];
		a = this->FindRoot(CapatMuchie1);
		b = this->FindRoot(CapatMuchie2);
		if( a != b )
		{
			nr_APM++;
			APM[nr_APM].x = CapatMuchie1;
			APM[nr_APM].y = CapatMuchie2;
			APM[nr_APM].cost = CostMuchie;                                  // se poate renunta la memorarea costului muchiilor din APM
			CostAPM = CostAPM + CostMuchie;
			this->Unite(CapatMuchie1,CapatMuchie2);                    // merge si cu a,b , e mai rapid
		}
	}
}

void Kruskal::printAPM()
{
	fprintf(out,"%d\n%d\n",CostAPM,n-1);
	for(int i = 1 ; i <= n-1 ; i++)
		fprintf(out,"%d %d\n",APM[i].x,APM[i].y);
}

int main()
{
	Kruskal G;
	G.Solve();
	G.printAPM();
	return 0;
}