Cod sursa(job #525878)

Utilizator mgntMarius B mgnt Data 26 ianuarie 2011 17:05:24
Problema Gather Scor 80
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.51 kb
#include <fstream>
#include <iostream>
#include <set>
#include <vector>
#include <limits>
using namespace std;

typedef long long lli;
lli const maxv=750,maxn=15,maxm=1250,
inf = (numeric_limits<lli>::max())/20;
struct hamiltonian_path
{

struct weight
{
lli x,w;
bool operator<(weight const&o)const
{return (w==o.w)?(x<o.x):(w<o.w);}
};

struct weights
{
lli n,V[maxv];
set<weight> W;

lli pop_min()
{	weight const&e=*W.begin();
	//cout<<"pop: " << e.x << " " << e.w << endl;
	lli x=e.x;W.erase(W.begin());
	return x;
}

void decrease(lli x,lli w)
{	if(V[x]>w)
	{	//cout<<"decrease: " << x << " " << w << endl;	
		weight e;e.x=x;e.w=V[x];
		W.erase(W.find(e));
		e.w=V[x]=w;W.insert(e);
	}
}

void init(lli an)
{	//cout<<"init"<<endl;	
	n=an;W.clear();
	lli x;weight e;
	for(x=0;n>x;++x)
	{e.x=x;e.w=V[x]=inf;W.insert(e);}
}

bool empty() const
{	return W.empty();	}

};

struct edge
{lli y,w,c;};

weights V;

vector<edge> A[maxv];
lli
m,v,

n,Y[maxn],W0[maxn],
W[1+maxn][maxn][maxn],

D[1<<maxn][1+maxn];

lli C[1<<maxn];

void compute_cardinal()
{	lli t=(1<<n)-1,s,lsb;
	C[0]=0;
	for(s=1;t>=s;++s)
	{	lsb=(s&-s);
		C[s]=1+C[s^lsb];
	}
}

void dijkstra(lli s,lli h)
{	lli x,t,i,y,w,c;	
	V.init(v);	
	V.decrease(s,0);
	while(!V.empty())
	{	x=V.pop_min();
		t=(lli)A[x].size();
		for(i=0;t>i;++i)
		{	y=A[x][i].y;
			w=A[x][i].w;
			c=A[x][i].c;
			if(h<=c)
			{	V.decrease(y,V.V[x]+w);	}
		}
	}
}

void add_weights(lli i,lli h)
{	lli j;	
	for(j=0;n>j;++j)
	{W[h][i][j]=V.V[Y[j]];}
}

void compute_weights()
{	lli h,i;
	
	dijkstra(0,0);
	for(i=0;n>i;++i)
	{W0[i]=V.V[Y[i]];}
	
	for(h=1;n>=h;++h)
	{	for(i=0;n>i;++i)
		{	dijkstra(Y[i],h);
			add_weights(i,h);
		}
	}
}

lli get_minimum_weight()
{	compute_weights();
	compute_cardinal();
	lli x,t,s,v,y,bx,by,b;
	
	t=(1<<n)-1;

	for(s=1;t>=s;++s)
	{	for(x=0;n>x;++x)
		{D[s][x]=inf;}
	}
	
	for(x=0;n>x;++x)
	{D[1<<x][x]=W0[x];}
		
	for(s=1;t>=s;++s)
	{	for(x=0;n>x;++x)
		{	bx=(1<<x);
			if(s&bx)
			{	for(y=0;n>y;++y)
				{	by=(1<<y);
					if(0==(s&by))
					{	v=D[s][x]+(C[s]+1)*W[C[s]][x][y];
						if(v<D[s|by][y]){D[s|by][y]=v;}
					}
				}
			}
		}
	}
	
	b=inf;
	for(y=0;n>y;++y)
	{	if(b>D[t][y]){b=D[t][y];}	}
	
	return b;
}

};

hamiltonian_path H;

int main()
{	ifstream is("gather.in");
	ofstream os("gather.out");
	lli k,n,m,i,y,a,b,c,d;
	hamiltonian_path::edge e;
	is>>k>>n>>m;
	H.n=k;H.v=n;
	for(i=0;k>i;++i)
	{is>>y;--y;H.Y[i]=y;}
	for(i=0;m>i;++i)
	{	is>>a>>b>>c>>d;
		--a;--b;e.w=c;e.c=d;
		e.y=b;H.A[a].push_back(e);
		e.y=a;H.A[b].push_back(e);
	}
	a=H.get_minimum_weight();
	os<<a<<endl;
	return 0;
}