Cod sursa(job #584441)

Utilizator mihai_floreaFlorea Mihai Alexandru mihai_florea Data 25 aprilie 2011 15:44:31
Problema Ubuntzei Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.49 kb
#include <fstream>
#include <vector>
using namespace std;

const int NMAX = 2002;
const int KMAX = 15;
const int Inf = 0x3f3f3f3f;
const long long INF = 6666666666666666LL;

#define ff first
#define ss second
#define mp make_pair
#define pb push_back

int N, M, K;
vector< pair<int, int> > G[NMAX];
vector<int> C;

void read()
{
	ifstream fin("ubuntzei.in");
	fin>>N>>M>>K;
	C.resize(K+2);
	for (int i=1;i<=K;++i) fin>>C[i];
	while (M--)
	{
		int i, j, k;
		fin>>i>>j>>k;
		G[i].pb(mp(j, k));
		G[j].pb(mp(i, k));
	}
	fin.close();
}

int h[NMAX],d[NMAX],p[NMAX];

void heap_up(int k)
{
	while (k>1 && d[h[k>>1]]>d[h[k]])
	{
		swap(h[k>>1], h[k]);
		p[h[k]]=k;
		k>>=1;
	}
	p[h[k]]=k;
}

void heap_down(int k)
{
	while (1)
	{
		int son=k<<1;
		if (son > h[0]) break;
		if (son+1 <= h[0] && d[h[son+1]]<d[h[son]]) ++son;
		if (d[h[k]] <= d[h[son]]) break;
		swap(h[k], h[son]);
		p[h[k]]=k;
		k=son;
	}
	p[h[k]]=k;
}

void heap_build()
{
	for (int i=h[0]>>1;i;--i) heap_down(i);
}

int heap_extractmin()
{
	int ret=h[1];
	swap(h[1], h[h[0]--]);
	p[h[1]]=1;
	heap_down(1);
	return ret;
}

void dijkstra(int source)
{
	for (int i=1;i<=N;++i) d[i]=Inf;
	d[source]=0;
	h[0]=N;
	for (int i=1;i<=N;++i) h[i]=i, p[i]=i;
	heap_build();
	for (int i=1;i<=N;++i)
	{
		int x=heap_extractmin();
		for (vector< pair<int, int> >::iterator it=G[x].begin();it!=G[x].end();++it)
			if (d[it->ff] > d[x]+it->ss)
			{
				d[it->ff]=d[x]+it->ss;
				heap_up(p[it->ff]);
			}
	}
}

int a[KMAX+2][KMAX+2];

void build_a()
{
	dijkstra(3);
	C[0]=1;C[K+1]=N;
	for (int i=0;i<K+2;++i)
	{
		dijkstra(C[i]);
		for (int j=0;j<K+2;++j)
			a[i][j]=d[C[j]];
	}

	for (int i=0;i<K+2;++i)
	{
		for (int j=0;j<K+2;++j) printf("%d ",a[i][j]);
		printf("\n");
	}
}

long long din[1<<KMAX][KMAX+1];

void solve() //find min-cost hamiltonian path
{
	for (int j=0;j<(1<<K);++j)
		for (int i=0;i<K+1;++i)
			din[j][i]=INF;
	din[0][0]=0;
	for (int i=1;i<(1<<K);++i)
	{
		for (int j=1;j<K+1;++j)
		{
			int r=i^(1<<(j-1));
			if (r == 0) { din[i][j] = a[0][j]; continue; }
			if (!((1<<(j-1))&i)) continue;
			for (int k=1;k<K+1;++k)
				if (k!=j && ((1<<(k-1))&i))
					din[i][j] = min(din[i][j], din[r][k]+a[k][j]);
		}
	}

	long long ans=INF;
	for (int i=0;i<=K;++i)
		ans=min(ans, din[(1<<K)-1][i] + a[i][K+1]);

	ofstream fout("ubuntzei.out");
	fout<<ans<<"\n";
	fout.close();
}

int main()
{
	read();
	build_a();
	solve();
	return 0;
}