Cod sursa(job #840475)

Utilizator arrayAnghel Mihai array Data 22 decembrie 2012 19:00:43
Problema Ubuntzei Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.48 kb
#include <iostream>
#include <fstream>
#include <vector>
#include <set>
#include <cstring>
#define NMAX 2011
#define KMAX 17
#define INF 0x3f3f3f3f
using namespace std;

int N, M, K;
int sol = INF;
vector<int> special;
vector< pair<int, int> > A[NMAX];
set< pair<int, int> > S;
int _dist[NMAX];
int dist[KMAX][KMAX];
bool ap[NMAX];
int dp[1 << KMAX][KMAX];

void read()
{
	ifstream fin("ubuntzei.in");
	int x, y, cost;
	fin >> N >> M >> K;
	special.push_back(1);
	for (int i = 0; i < K; ++i)
	{
		fin >> x;
		special.push_back(x);
	}
	special.push_back(N);
	K += 2;
	for (int i = 1; i <= M; ++i)
	{
		fin >> x >> y >> cost;
		A[x].push_back(make_pair(y, cost));
		A[y].push_back(make_pair(x, cost));
	}
}

void dijkstra(int start)
{
	while (S.size()) S.erase(*S.begin());
	S.insert(make_pair(0, start));
	memset(_dist, INF, sizeof(_dist));
	memset(ap, false, sizeof(ap));
	_dist[start] = 0;
	while (S.size())
	{
		int nod = S.begin()->second;
		S.erase(*S.begin());
		if (ap[nod]) continue;
		ap[nod] = true;
		for (vector< pair<int, int> >::iterator it = A[nod].begin(); it != A[nod].end(); ++it)
		{
			if (_dist[it->first] > _dist[nod] + it->second)
			{
				S.erase(make_pair(_dist[it->first], it->first));
				_dist[it->first] = _dist[nod] + it->second;
				S.insert(make_pair(_dist[it->first], it->first));
			}
		}
	}
}

void doit()
{
	for (int i = 0; i < K; ++i)
	{
		dijkstra(special[i]);
		for (int j = 0; j < K; ++j)
		{
			dist[i][j] = _dist[special[j]];
		}
	}
}

void dinamika()
{
	for (int i = 0; i < (1 << KMAX); ++i)
	{
		for (int j = 0; j < KMAX; ++j)
		{
			dp[i][j] = INF;
		}
	}
	
	// 1  ,  nodurile  ,  N
	
	for (int i = 1; i < K; ++i)
    {
        dp[(1 << i) + 1][i] = dist[0][i];
    }
    int i, j, k;
    for (i = 1; i < (1 << K); i += 2)
    {
        for (int j = 0; j < K - 1; ++j)
        {
            if (dp[i][j] != INF)
            {
                for (int k = 1; k < K; ++k)
                {
                    if (!(i & (1 << k)))
                    {
                        dp[i | (1 << k)][k] = min(dp[i | (1 << k)][k], dp[i][j] + dist[j][k]);
                    }
                }
            }
        }
    }
}

void write()
{
	ofstream fout("ubuntzei.out");
	for (int i = 0; i < K; ++i)
	{
		sol = min(sol, dp[(1 << K) - 1][i]);
	}
	fout << sol << '\n';
	cout << sol << '\n';
	fout.close();
}

int main()
{
	read();
	doit();
	dinamika();
	write();
	return 0;
}