Cod sursa(job #611716)

Utilizator PlayLikeNeverB4George Marcus PlayLikeNeverB4 Data 2 septembrie 2011 19:51:46
Problema Ubuntzei Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.31 kb
#include <stdio.h>
#include <vector>
#define pb push_back
#define mp make_pair
#define ff first
#define ss second
#define maxn 2011
#define maxk 16
#define INF 2000000000
using namespace std;

int i,j,k,N,M,K;
int U[maxn];
vector<pair<int,int> > A[maxn];
vector<pair<int,int> > :: iterator it;
int H[maxn],poz[maxn],hp;
int orig[maxn], dist[maxn][maxn],dp[(1<<maxk)][maxk];

void citire()
{
	int x,y,z;
	scanf("%d %d",&N,&M);
	scanf("%d",&K);
	for(i=0;i<K;i++)
		scanf("%d",&U[i]);
	for(i=1;i<=M;i++)
	{
		scanf("%d %d %d",&x,&y,&z);
		A[x].pb(mp(y,z));
		A[y].pb(mp(x,z));
	}
}

void swap(int &a, int &b) {
	int aux=a; a=b; b=aux;
}
void upheap(int D[maxn], int k) {
	while(k>1 && D[H[k]]<D[H[k/2]]) {
		swap(H[k],H[k/2]);
		swap(poz[H[k]],poz[H[k/2]]);
		k/=2;
	}
}
void downheap(int D[maxn], int k) {
	int son;
	do {
		son=0;
		if(2*k<=hp) {
			son=2*k;
			if(2*k+1<=hp && D[H[son]]<D[H[son+1]]) son++;
		}
		if(son) {
			swap(H[k],H[son]);
			swap(poz[H[k]],poz[H[son]]);
			k=son;
		}
	}while(son);
}
void insert(int D[maxn], int nod) {
	H[++hp]=nod;
	poz[nod]=hp;
	upheap(D,hp);
}
int radacina(int D[maxn]) {
	int r=H[1];
	poz[H[1]]=0;
	poz[H[hp]]=1;
	swap(H[1],H[hp]);
	hp--;
	downheap(D,1);
	return r;
}
void dijkstra(int start, int D[maxn]) {
	int x;
	for(int i=1;i<=N;i++) { D[i]=INF; H[i]=poz[i]=0; }
	insert(D,start); D[start]=0;
	while(hp) {
		x=radacina(D);
		for(it=A[x].begin();it!=A[x].end();it++)
			if(D[x] + it->ss < D[it->ff]) {
				D[it->ff]=D[x] + it->ss;
				if(poz[it->ff]==0)
					insert(D,it->ff);
				else
					upheap(D,poz[it->ff]);
			}
	}
}

int main()
{
	freopen("ubuntzei.in","r",stdin);
	freopen("ubuntzei.out","w",stdout);
	citire();
	dijkstra(1,orig);
	
	if(K==0) {
		printf("%d",orig[N]);
		return 0;
	}
	
	for(i=0;i<K;i++)
		dijkstra(U[i],dist[i]);
	
	for(i=1;i<(1<<K);i++) {
		
		if((i&(i-1))==0) {
			for(j=0;j<K;j++)
				if((i&(1<<j))>0) break;
			
			dp[i][j]=orig[U[j]];
			continue;
		}
		
		for(j=0;j<K;j++) {
			dp[i][j]=INF;
			if((i&(1<<j))>0)
				for(k=0;k<K;k++) {
					if(k==j || (i&(1<<k))==0) continue;
					
					dp[i][j]=min(dp[i][j], dp[i-(1<<j)][k] + dist[k][U[j]]);
				}
		}
	}
	
	int Min=INF;
	for(k=0;k<K;k++)
		Min=min(Min, dp[(1<<K)-1][k] + dist[k][N]);
	printf("%d",Min);
}