Cod sursa(job #667696)

Utilizator mihaipopa12Popa Mihai mihaipopa12 Data 23 ianuarie 2012 17:09:23
Problema Ubuntzei Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.23 kb
#include<stdio.h>
#include<vector>
#include<cstdlib>

#define maxn 2005
#define maxk 15
#define INF (1<<29)
#define pb push_back
#define mp make_pair

using namespace std;

FILE*f=fopen("ubuntzei.in","r");
FILE*g=fopen("ubuntzei.out","w");

int n,m,k;
int L,H[maxn],Poz[maxn];
int A[maxk+5],D[maxn],dist[maxk+5][maxk+5],best[maxk+1][(1<<maxk)+5];
vector< pair<int,int> >G[maxn];

inline void citire () {
	
	fscanf(f,"%d %d",&n,&m);
	
	fscanf(f,"%d",&k);
	for ( int i = 1 ; i <= k ; ++i ){
		fscanf(f,"%d",&A[i]);
	}
	
	int x,y,c;
	for ( int i = 1 ; i <= m ; ++i ){
		fscanf(f,"%d %d %d",&x,&y,&c);
		G[x].pb(mp(y,c));
		G[y].pb(mp(x,c));
	}
}

inline void swap ( int &a , int &b ){
	int aux = a; a = b; b = aux;
}

inline void urca ( int poz ){
	
	while ( poz > 1 && D[H[poz>>1]] > D[H[poz]] ){
		swap(H[poz>>1],H[poz]);
		swap(Poz[H[poz>>1]],Poz[H[poz]]);
		poz >>= 1;
	}
}

inline void coboara ( int x ){
	int y = 0;
	
	while ( x != y ){
		y = x;
		
		if ( (y<<1) <= L && D[H[y<<1]] < D[H[x]] ){
			x = (y<<1);
		}
		if ( (y<<1)+1 <= L && D[H[(y<<1)+1]] < D[H[x]] ){
			x = (y<<1) + 1;
		}
		
		swap(H[x],H[y]);
		swap(Poz[H[x]],Poz[H[y]]);
	}
}

inline void add_heap ( int nod ){
	H[++L] = nod; Poz[nod] = L; urca(L); 
}

inline void delete_first (){
	
	swap(H[1],H[L]); swap(Poz[H[1]],Poz[H[L]]); --L;
	coboara(1);
}

inline void dijkstra ( int start ) {
	int i;
	
	for ( i = 1 ; i <= n ; ++i ){
		D[i] = INF; Poz[i] = 0;
	}
	D[start] = 0;
	
	L = 0;
	add_heap(start);
	
	int nod,nodvcn,cstvcn;
	
	while ( L ){
		nod = H[1]; delete_first();
		
		for ( vector< pair<int,int> >::iterator itt = G[nod].begin() ; itt != G[nod].end() ; ++itt ){
			nodvcn = itt->first; cstvcn = itt->second;
			if ( D[nodvcn] > D[nod] + cstvcn ){
				D[nodvcn] = D[nod] + cstvcn;
				if ( Poz[nodvcn] ){
					urca(Poz[nodvcn]);
				}
				else{
					add_heap(nodvcn);
				}
			}
		}
	}
}

inline void compute_distances () {
	int i,j;
	
	for ( i = 1 ; i <= k ; ++i ){
		dijkstra(A[i]);
		for ( j = 1 ; j <= k ; ++j ){
			dist[i][j] = D[A[j]];
		}			
	}
	
	dijkstra(1);
	for ( i = 1 ; i <= k ; ++i ){
		dist[0][i] = D[A[i]];
	}
	dijkstra(n);
	
	if ( !k ){
		fprintf(g,"%d\n",D[1]);
		fclose(f); fclose(g);
		exit(0);
	}
	
	for ( i = 1 ; i <= k ; ++i ){
		dist[k+1][i] = D[A[i]];
	}
}

inline int min ( int a , int b ){
	return a <= b ? a : b;
}

inline void solve () {
	int i,j,index;
	
	for ( i = 1 ; i <= k ; ++i ){
		for ( j = 1 ; j < (1<<k) ; ++j ){
			best[i][j] = INF;
		}
	}
	for ( i = 1 ; i <= k ; ++i ){
		best[i][1<<(i-1)] = dist[0][i];
	}
	
	for ( i = 1 ; i < (1<<k) ; ++i ){
		for ( j = 1 ; j <= k ; ++j ){
			if ( (i & (1<<(j-1))) > 0 ){
				int prev = i^(1<<(j-1));
				
				if ( prev ){
					for ( index = 1 ; index <= k ; ++index ){
						if ( index != j && ((i & (1<<(index-1))) > 0) ){
							best[j][i] = min(best[j][i],best[index][prev]+dist[j][index]);
						}
					}
				}
			}
		}
	}
	
	int sol = INF;
	for ( i = 1 ; i <= k ; ++i ){
		sol = min(sol,best[i][(1<<k)-1] + dist[k+1][i]);
	}
	
	fprintf(g,"%d\n",sol);
}

int main () {
	
	citire();
	compute_distances();
	solve();
	
	fclose(f);
	fclose(g);
	
	return 0;
}