Cod sursa(job #48361)

Utilizator MarcvsHdrMihai Leonte MarcvsHdr Data 4 aprilie 2007 18:29:15
Problema Radiatie Scor 0
Compilator cpp Status done
Runda Arhiva de probleme Marime 6.06 kb
# include <stdio.h>
# include <stdlib.h>

const long int
	MAXM=30000,
	MAXK=15000,
	MAXN=15000;
typedef struct MUCHIE {long int a,b,cost;};
struct {long int a,b,answ;} task[MAXK+1];
MUCHIE muc[MAXM+1],heap[MAXM+1];
long int n,m,k,heaplen,tata[MAXN+1],listlen,rad,chainlen;
struct {long int next,info;} ladiac[MAXN+1];
typedef struct NOD {long int prim,ultim,tata,cost,niv;};
typedef struct NOD_ARB_DINT {NOD_ARB_DINT *drta,*stga; long int lca;};
NOD_ARB_DINT *raddint;
NOD nod[MAXN+1];
long int chain[3*MAXN+1],first[MAXN+1];

//////////////////////////////////////////////////
// HEAP INTERFACE
//////////////////////////////////////////////////

void float_heap(long int i)
{
MUCHIE aux;
while (i!=1&&heap[i/2].cost>heap[i].cost)
	{
	aux=heap[i/2];
	heap[i/2]=heap[i];
	heap[i]=aux;
	i/=2;
	}
}

void create_heap()
{
long int i;
for (i=1;i<=m;i++)
	{
	heap[++heaplen]=muc[i];
	float_heap(heaplen);
	}
}

void submerge_heap(long int i)
{
MUCHIE aux;
long int min=i;
if (2*i<=heaplen&&heap[2*i].cost<heap[min].cost) min=2*i;
if (2*i+1<=heaplen&&heap[2*i+1].cost<heap[min].cost) min=2*i+1;
if (min!=i)
	{
	aux=heap[i];
	heap[i]=heap[min];
	heap[min]=aux;
	submerge_heap(min);
	}
}

//////////////////////////////////////////////////
// DISJOINT SET STRUCTURE INTERFACE
//////////////////////////////////////////////////

void init_set()
{
long int i;
for (i=1;i<=n;i++) tata[i]=i;
}

long int find_set(long int ord)
{
long int s=ord;
while (tata[ord]!=ord) ord=tata[ord];
tata[s]=ord;
return ord;
}

void merge(long int o1, long int o2) {tata[o2]=o1;}

//////////////////////////////////////////////////
// CREATE MINIMUM SPAN TREE
//////////////////////////////////////////////////

void kruskall()
{
create_heap();
long int i;
for (i=1;i<=n-1;i++)
	{
	while (find_set(heap[1].a)==find_set(heap[1].b))
		{
		heap[1]=heap[heaplen];
		heaplen--;
		submerge_heap(1);
		}
	muc[i]=heap[1];
	merge(find_set(heap[1].a),find_set(heap[1].b));
	heap[1]=heap[heaplen];
	heaplen--;
	submerge_heap(1);
	}
}

void add_node(long int loc, long int val, long int cost)
{
ladiac[++listlen].info=val;
ladiac[listlen].next=0;
nod[val].cost=cost;
if (nod[loc].prim==0)
	{
	nod[loc].prim=listlen;
	nod[loc].ultim=listlen;
	}
else
	{
	ladiac[nod[loc].ultim].next=listlen;
	nod[loc].ultim=listlen;
	}
}

void create_tree_structure()
{
long int i;int sel[MAXN+1]={0};
for (i=1;i<=n-1;i++)
	{
	if (sel[muc[i].b]==0)
		add_node(muc[i].a,muc[i].b,muc[i].cost);
	else 	add_node(muc[i].b,muc[i].a,muc[i].cost);
	if (sel[muc[i].a]==sel[muc[i].b]&&sel[muc[i].a]==0) rad=muc[i].a;
	sel[muc[i].a]=1;
	sel[muc[i].b]=1;
	}
}

//////////////////////////////////////////////////
// CREATE CHAIN AND PERFORM DFS ON TREE
//////////////////////////////////////////////////

void df_and_create_chain(long int node, long int tata, long int niv)
{
nod[node].niv=niv;
nod[node].tata=tata;
chain[++chainlen]=node;
long int p=nod[node].prim;
while (p!=0)
	{
	df_and_create_chain(ladiac[p].info,node,niv+1);
	p=ladiac[p].next;
	chain[++chainlen]=node;
	}
}

void prepare_nodes()
{
long int i;
for (i=1;i<=chainlen;i++)
	if (first[chain[i]]==0) first[chain[i]]=i;
}

//////////////////////////////////////////////////
// SEGMENT TREE INTERFACE
//////////////////////////////////////////////////

void aloca_arb_dint(NOD_ARB_DINT *p, long int li, long int lf)
{
NOD_ARB_DINT *q;
long int mij=(li+lf)/2;
if (li!=lf)
	{
	q=(NOD_ARB_DINT*) malloc (sizeof(NOD_ARB_DINT));
	(*q).lca=0;
	(*p).stga=q;
	aloca_arb_dint(q,li,mij);
	q=(NOD_ARB_DINT*) malloc (sizeof(NOD_ARB_DINT));
	(*q).lca=0;
	(*p).drta=q;
	aloca_arb_dint(q,mij+1,lf);
	}
else
	{
	(*p).drta=NULL;
	(*p).stga=NULL;
	}
}

void update(NOD_ARB_DINT *p, long int a, long int li, long int lf)
{
long int mij=(li+lf)/2;
if ((*p).lca==0||nod[chain[a]].niv<nod[(*p).lca].niv)
	{
	(*p).lca=chain[a];
	}
if (a!=li||a!=lf)
if (a<=mij)
	update((*p).stga,a,li,mij);
else
	update((*p).drta,a,mij+1,lf);
}

void create_segment_tree()
{
long int i;
for (i=1;i<=chainlen;i++)
	update(raddint,i,1,chainlen);
}

long int lca(NOD_ARB_DINT *p,long int a, long int b, long int li, long int lf)
{
long int mij=(li+lf)/2;
if (a<=li&&lf<=b) return (*p).lca;
long int w=0,ww=0;
if (a<=mij) w=lca((*p).stga,a,b,li,mij);
if (b>mij) ww=lca((*p).drta,a,b,mij+1,lf);
if (w!=0&&ww!=0)
	{
	if (nod[w].niv>nod[ww].niv) w=ww;
	}
else if (w==0) w=ww;
return w;
}

void print_tree(NOD_ARB_DINT *p, long int li, long int lf)
{
long int mij=(li+lf)/2;
printf("%ld %ld : %ld\n",li,lf,(*p).lca);
if ((*p).stga) print_tree((*p).stga,li,mij);
if ((*p).drta) print_tree((*p).drta,mij+1,lf);
}

//////////////////////////////////////////////////
// MAIN SOLVE FUNCTION
//////////////////////////////////////////////////

long int find_max(long int a, long int b)
{
long int sol=0;
if (a!=b)
	{
	sol+=nod[a].cost;
	a=nod[a].tata;
	}
return sol;
}

void solve()
{
long int i,aux,answ1,answ2;
for (i=1;i<=k;i++)
	{
	aux=lca(raddint,first[task[i].a],first[task[i].b],1,chainlen);
	answ1=find_max(task[i].a,aux);
	answ2=find_max(task[i].b,aux);
	if (answ1>answ2) task[i].answ=answ1;
	else task[i].answ=answ2;
	}
}


//////////////////////////////////////////////////
// MAIN AND MAIN PROGRAM'S INTERFACE
//////////////////////////////////////////////////

void citire()
{
FILE *f=fopen("radiatie.in","r");
fscanf(f,"%ld%ld%ld",&n,&m,&k);
long int i;
for (i=1;i<=m;i++)
	fscanf(f,"%ld%ld%ld",&muc[i].a,&muc[i].b,&muc[i].cost);
for (i=1;i<=k;i++)
	fscanf(f,"%ld%ld",&task[i].a,&task[i].b);
fclose(f);
}

void scrie()
{
FILE *g=fopen("radiatie.out","w");
long int i;
for (i=1;i<=k;i++)
	fprintf(g,"%ld\n",task[i].answ);
fcloseall();
}

int main()
{
citire();
init_set();
kruskall();
create_tree_structure();
df_and_create_chain(rad,0,1);
raddint=(NOD_ARB_DINT*) malloc (sizeof(NOD_ARB_DINT));
(*raddint).lca=0;
aloca_arb_dint(raddint,1,chainlen);
/*create_segment_tree();
prepare_nodes();
solve();
print_tree(raddint,1,chainlen);
scrie();*/
return 0;
}