Cod sursa(job #206601)

Utilizator mariusdrgdragus marius mariusdrg Data 7 septembrie 2008 22:26:12
Problema Gather Scor 80
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.21 kb
#include<stdio.h>
#include<algorithm>
#include<set>
#include<vector>
#define mkp make_pair
#define pb push_back

using namespace std;

const int maxst = 65000,maxn = 770,maxk = 17;
const int INF = 2000000000;

set <pair<long long,int> > SE;
vector <pair< int,pair <int,int> > > VECT[maxn];
long long POZ[maxn],DIST[maxn],D[maxk][maxk][maxn];
long long NRB[maxst],K,M,N,A[maxk][maxst];


void dijkstra(int lim,int nod)
{
	while(!SE.empty())
	{
		set <pair<long long,int> > :: iterator it1 = SE.begin();
		int nod = (*it1).second;
                for(vector<pair <int, pair <int,int> > > :: iterator it = VECT[nod].begin();it != VECT[nod].end(); ++it)
		{
			int vec = (*it).first;
			int cap = (*it).second.first;
			int cost = (*it).second.second;
			if (cap < lim) continue;
			if (DIST[vec] > DIST[nod] + cost)
			{
				SE.erase(SE.find(mkp(DIST[vec],vec)));
				DIST[vec] = DIST[nod] + cost;
				SE.insert(mkp(DIST[vec],vec));
			}
		}
		SE.erase(it1);
	}
	memcpy(D[lim][nod],DIST,sizeof(DIST));
}

int main()
{
	freopen("gather.in","r",stdin);
	freopen("gather.out","w",stdout);
	scanf("%lld %lld %lld\n",&K,&N,&M);
	for(int i = 1;i <= K; ++i)
		scanf("%lld\n",&POZ[i]);
	for(int i = 1;i <= M; ++i)
	{
		int a,b,cap,cost;
		scanf("%d %d %d %d\n",&a,&b,&cost,&cap);
		VECT[a].pb(mkp(b,mkp(cap,cost)));
		VECT[b].pb(mkp(a,mkp(cap,cost)));
	}
        POZ[0] = 1;
	for(int l = 0;l <= K; ++l)
	{
		for(int i = 0;i <= K; ++i)
		{
			memset(DIST,1,sizeof(DIST));
			DIST[POZ[i]] = 0;
			for(int j = 1;j <= N; ++j)
				SE.insert(mkp(DIST[j],j));
			dijkstra(l,i);
		}
	}
	for(int i = 1;i <= (1 << (K + 1)); ++i)
	{
		for(int p = 1;p <= i;p <<= 1)
			NRB[i] += ((i & p) != 0);
	}
	memset(A,1,sizeof(A));
        A[0][1] = 0;
	long long SOL = INF;
	for(int i = 1;i < (1 << (K + 1)); ++i)
	{
		for(int j = 0;j <= K; ++j)
		{
                        if (A[j][i] > INF) continue;
			if (i == (1 << (K + 1)) - 1)
                        {
                                SOL = min((long long)SOL,A[j][i]);
                        }
			for(int p = 1;p <= K; p++)
			{
                                if ((i & (1 << p)) == 0) A[p][i | (1 << p)] = min((long long)A[p][i | (1 << p)],A[j][i] + NRB[i] * D[NRB[i] - 1][j][POZ[p]]);
			}
		}
	}
	printf("%lld\n",SOL);
	return 0;
}