Cod sursa(job #811655)

Utilizator ChallengeMurtaza Alexandru Challenge Data 12 noiembrie 2012 19:40:18
Problema Gather Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.48 kb
#include <fstream>
#include <vector>
#include <queue>

using namespace std;

const char InFile[]="gather.in";
const char OutFile[]="gather.out";
const int MaxN=752;
const int MaxK=16;
const int MaxConf=(1<<MaxK);
const long long INF=(1LL<<50);

ifstream fin(InFile);
ofstream fout(OutFile);

struct EdgeTo
{
	EdgeTo(int to=0, int cost=0, int lim=0):to(to),cost(cost),lim(lim){}

	int to,cost,lim;
};

int N,K,M,x,y,c,lim,Room[MaxK],inQ[MaxN],nr1[MaxConf],T[MaxN];
long long sol,C[MaxK][MaxK+1][MaxN],SOL[MaxK][MaxConf];
vector<EdgeTo> G[MaxN];
queue<int> Q;

inline void BellmanFord(int nod, int lim, long long *D)
{
	for(register int i=1;i<=N;++i)
	{
		D[i]=INF;
		T[i]=0;
	}
	D[nod]=0;

	Q.push(nod);
	inQ[nod]=1;
	while(!Q.empty())
	{
		nod=Q.front();
		Q.pop();
		inQ[nod]=0;
		if(inQ[T[nod]])
		{
			continue;
		}

		for(vector<EdgeTo>::iterator it=G[nod].begin();it!=G[nod].end();++it)
		{
			if(it->lim<lim)
			{
				continue;
			}
			if(D[it->to]>D[nod]+it->cost)
			{
				D[it->to]=D[nod]+it->cost;
				T[it->to]=nod;
				if(!inQ[it->to])
				{
					inQ[it->to]=1;
					Q.push(it->to);
				}
			}
		}
	}
	for(register int i=1;i<=N;++i)
	{
		D[i]*=(lim+1);
	}
}

inline int CountBits(int nr)
{
	int sol=0;
	while(nr)
	{
		++sol;
		nr&=(nr-1);
	}
	return sol;
}

int main()
{
	fin>>K>>N>>M;
	for(register int i=0;i<K;++i)
	{
		fin>>Room[i];
	}
	for(register int i=0;i<M;++i)
	{
		fin>>x>>y>>c>>lim;
		G[x].push_back(EdgeTo(y,c,lim));
		G[y].push_back(EdgeTo(x,c,lim));
	}
	fin.close();

	for(register int lim=1;lim<K;++lim)
	{
		for(register int j=0;j<K;++j)
		{
			BellmanFord(Room[j],lim,C[lim][j+1]);
		}
	}
	BellmanFord(1,0,C[0][0]);

	int EndConf=(1<<K)-1;
	for(register int i=1;i<=EndConf;++i)
	{
		nr1[i]=CountBits(i);
	}

	for(register int i=0;i<=K;++i)
	{
		for(register int j=0;j<=EndConf;++j)
		{
			SOL[i][j]=INF;
		}
	}
	SOL[0][0]=0;

	for(register int conf=0;conf<=EndConf;++conf)
	{
		int start=1;
		if(conf==0)
		{
			start=0;
		}
		for(register int nod=start;nod<=K;++nod)
		{
			int nextConf=conf;
			if(nod!=0)
			{
				nextConf=nextConf|(1<<(nod-1));
			}
			for(register int nextNod=1;nextNod<=K;++nextNod)
			{
				SOL[nextNod][nextConf]=min(SOL[nextNod][nextConf],SOL[nod][conf]+C[nr1[nextConf]][nod][Room[nextNod-1]]);
			}
		}
	}

	sol=INF;
	for(register int i=1;i<=K;++i)
	{
		sol=min(sol,SOL[i][EndConf]);
	}

	fout<<sol;
	fout.close();
	return 0;
}