Cod sursa(job #581161)

Utilizator AndreyPAndrei Poenaru AndreyP Data 13 aprilie 2011 20:31:17
Problema Ubuntzei Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.75 kb
#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std;
#define fs first
#define sc second
#define mp make_pair
#define pii pair< int,int >
#define pb push_back
#define N 2010
#define ll long long
#define K 15

int n,k;
vector< pii > g[N];
int h[N],nh,inheap[N];
ll d[N];
ll a[(1<<K)][K];
int c[K];
const ll inf = 1LL<<62;
ll cost[K][K];
ll coststart[K],costend[K];

inline void citire() {
	int m;
	scanf("%d%d",&n,&m);
        scanf("%d",&k);

	for(int i=0; i<k; ++i)
		scanf("%d",&c[i]);

	int x,y,z;
	for(int i=0; i<m; ++i) {
		scanf("%d%d%d",&x,&y,&z);
		g[x].pb(mp(y,z));
		g[y].pb(mp(x,z));
	}
}

inline int left_son(int x) {
	return (x<<1);
}

inline int right_son(int x) {
	return ((x<<1)+1);
}

inline int father(int x) {
	return (x>>1);
}

inline void upheap(int k) {
	int key = h[k];

	while(k>1 && d[key]<d[h[father(k)]]) {
		h[k] = h[father(k)];
		inheap[h[k]] = k;
		k = father(k);
	}

	h[k] = key;
	inheap[h[k]] = k;
}

inline void downheap(int k) {
	int son = 0;

	do{ 
		son = 0;
		if(left_son(k)<=nh) {
			son = left_son(k);
			if(right_son(k)<=nh && d[h[right_son(k)]]<d[h[son]])
				son = right_son(k);
			if(d[son]>=d[k])
				son = 0;
		}
		if(son) {
			swap(h[k],h[son]);
			inheap[h[k]] = k;
			inheap[h[son]] = son;
			k = son;
		}
	}while(son!=0);
}

inline void dijkstra(int now) {
	for(int i=1; i<=n; ++i) {
		inheap[i] = 0;
		d[i] = inf;
	}
	d[now] = 0LL;
	nh = 1;
	h[1] = now;
	inheap[now] = 1;
	int next;
	ll cost;

	while(nh>0) {
		now = h[1];
		inheap[now] = 0;
		if(nh>1) {
			h[1] = h[nh];
			--nh;
			inheap[h[1]] = 1;
			downheap(1);
		} else
			--nh;

		for(size_t i=0,lim=g[now].size(); i<lim; ++i) {
			next = g[now][i].fs;
			cost = g[now][i].sc+d[now];

			if(d[next]>cost) {
				d[next] = cost;

				if(inheap[next]!=0)
					upheap(inheap[next]);
				else {
					++nh;
					h[nh] = next;
					inheap[next] = nh;
					upheap(nh);
				}
			}
		}
	}
}

inline void rezolva() {
	if(k==0) {
		dijkstra(1);
		printf("%lld\n",d[n]);
		return;
	}

	for(int i=0; i<k; ++i) {
		dijkstra(c[i]);

		coststart[i] = d[1];
		costend[i] = d[n];
		for(int j=0; j<k; ++j)
			cost[i][j] = d[c[j]];
	}

	int lim = 1<<k;
	int i1;
	ll aux,aux1;
        for(int i=1; i<lim; ++i) {
		for(int j=0; j<k; ++j) {
			if((i&(1<<j))==0)
				continue;
			if(i==(1<<j)) {
				a[i][j] = coststart[j];
				continue;
			}

			i1 = (i^(1<<j));
			aux = inf;
			for(int t=0; t<k; ++t) {
				if((i1&(1<<t))==0)
					continue;
				aux1 = a[i1][t] + cost[j][t];
				if(aux1<aux)
					aux = aux1;
			}
			a[i][j] = aux;
		}
	}

	aux = inf;
	--lim;
	for(int i=0; i<k; ++i) {
        	aux1 = a[lim][i] + costend[i];
		if(aux1<aux)
			aux = aux1;
	}
	printf("%lld\n",aux);
}

int main() {
	freopen("ubuntzei.in","r",stdin);
	freopen("ubuntzei.out","w",stdout);

	citire();
	rezolva();

	return 0;
}