Cod sursa(job #799254)

Utilizator scipianusFMI Ciprian Olariu scipianus Data 18 octombrie 2012 14:14:28
Problema Gather Scor 80
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.79 kb
#include<fstream>
#include<queue>
#include<vector>
#include<cmath>
using namespace std;
int n,m,K,cel[20];
struct Muchie{int x,y,lg,maxim;};
Muchie M[1300];
vector <int> G[760];
struct Configuratie{int conf,x;};
queue <Configuratie> Q;
int dist[20][20][760],nr[33000],sol=2000000000,best[33000][20],dist1[760];
int detinut[760];

inline void Citire()
{
	int i;
	ifstream fin("gather.in");
	fin>>K>>n>>m;
	for(i=0;i<K;i++)
	{
		fin>>cel[i];
		detinut[cel[i]]=i+1;
	}
	for(i=1;i<=m;i++)
	{
		fin>>M[i].x>>M[i].y>>M[i].lg>>M[i].maxim;
		G[M[i].x].push_back(i);
		G[M[i].y].push_back(i);
	}
	fin.close();
}

inline void NumarBiti()
{
	int i,x;
	for(i=1;i<(1<<K);i++)
	{
		x=i;
		while(x)
		{
			if(x%2==1)
				nr[i]++;
			x/=2;
		}
	}
}

inline void BellmanFord(int start,int D,int dist[])
{
	queue <int> Q;
	int i,x,nod;
	vector <int>::iterator it;
	for(i=1;i<=n;i++)
		dist[i]=2000000000;
	dist[start]=0;
	Q.push(start);
	while(!Q.empty())
	{
		x=Q.front();
		Q.pop();
		for(it=G[x].begin();it!=G[x].end();it++)
		{
			nod=M[*it].x+M[*it].y-x;
			if(M[*it].maxim>=D && dist[nod]>dist[x]+M[*it].lg)
			{
				dist[nod]=dist[x]+M[*it].lg;
				if(detinut[nod]==false)
					Q.push(nod);
			}
		}
	}
}

inline void BellmanFord1(int start,int dist[])
{
	queue <pair<int,int> > Q;
	int i,x,d,nod,d2;
	vector <int>::iterator it;
	pair <int,int> aux;
	for(i=1;i<=n;i++)
		dist[i]=2000000000;
	dist[start]=0;
	if(detinut[start])
		Q.push(make_pair(start,1));
	else
		Q.push(make_pair(start,0));
	while(!Q.empty())
	{
		aux=Q.front();
		Q.pop();
		x=aux.first;
		d=aux.second;
		if(d==1)
			continue;
		for(it=G[x].begin();it!=G[x].end();it++)
		{
			nod=M[*it].x+M[*it].y-x;
			if(detinut[nod])
				d2=d+1;
			else
				d2=d;
			if(dist[nod]>dist[x]+M[*it].lg)
			{
				dist[nod]=dist[x]+M[*it].lg;
				Q.push(make_pair(nod,d2));
			}
		}
	}
}

inline void Distante()
{
	int i,j;
	for(i=0;i<K;i++)
		for(j=1;j<K;j++)
			BellmanFord(cel[i],j,dist[i][j]);
	BellmanFord1(1,dist1);
}

inline void Rezolvare()
{
	int i,j,conf;
	for(conf=0;conf<(1<<K);conf++)
		for(i=0;i<K;i++)
			best[conf][i]=2000000000;
	for(i=0;i<K;i++)
	{
		conf=(1<<i);
		best[conf][i]=dist1[cel[i]];
	}
	for(conf=3;conf<(1<<K);conf++)
	{
		for(i=0;i<K;i++)
		{
			if((conf&(1<<i))==0)
				continue;
			for(j=0;j<K;j++)
			{
				if((conf&(1<<j))==0 || j==i)
					continue;
				best[conf][i]=min(best[conf][i],best[conf-(1<<i)][j]+(nr[conf-(1<<i)]+1)*dist[j][nr[conf-(1<<i)]][cel[i]]);
			}
		}
	}
	for(i=0;i<K;i++)
		sol=min(sol,best[(1<<K)-1][i]);
}

inline void Afisare()
{
	ofstream fout("gather.out");
	fout<<sol<<"\n";
	fout.close();
}

int main()
{
	Citire();
	NumarBiti();
	Distante();
	Rezolvare();
	Afisare();
	return 0;
}