Cod sursa(job #696631)

Utilizator andunhillMacarescu Sebastian andunhill Data 28 februarie 2012 19:18:20
Problema Ubuntzei Scor 70
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.02 kb
#include<fstream>
#include<vector>
#include<queue>
using namespace std;

#define INF 1073741824
#define pii pair<int, int>

ifstream f("ubuntzei.in");
ofstream g("ubuntzei.out");

int N, M, K;

int last;

vector< pii >graph[2001];
int kgraph[16][16];

int kloc[16];			//special nodes 

int A[16][32769];		//cost of reaching in i with mask j
int kroad[17][2001];	//cost of road from k to i, k = special node
int kans[16][16];		//cost of road from i to j, where i and j - special nodes, reaching all k nodes

bool inq[16][32768];	//(i,j) is in queue
bool in[2001];			//i is in queue
bool isk[2001];			//is special



class cmp
{	public: bool operator()(pii a, pii b)
	{	return A[a.first][a.second] > A[b.first][b.second];
	}
};

class cmp1
{	public:
	
	static int *row;
	
	bool operator()(int a, int b)
	{	return row[a] > row[b];
	}
	
};

int *cmp1::row = NULL;


priority_queue<pii, vector< pii >, cmp>q;
priority_queue<int, vector<int>, cmp1>q1;

typedef vector< pii >::iterator it;

void init()
{	for(int i = 0; i <= K; i++)
		for(int j = 0; j <= 1<<K; j++)
			A[i][j] = INF;
}


void Dijkstra_exp(int node, int *D)
{	pii p;
	int conf, i, cost;
	
	init();
	
	A[node][1<<node] = 0; inq[node][1<<node] = true;
	q.push(make_pair(node, 1<<node)); conf = 1<<node;
	
	while(!q.empty())
	{	p = q.top(); q.pop();
		inq[p.first][p.second] = false;
		
		for(int i = 0; i < K; i++)
		{	cost = kgraph[p.first][i];
			if(i == p.first) continue;
			
			conf = p.second | (1<<i);
			
			if(A[i][conf] > A[p.first][p.second] + cost)
			{	A[i][conf] = A[p.first][p.second] + cost;
				
				if(!inq[i][conf])
				{	inq[i][conf] = true;
					q.push(make_pair(i, conf));
				}
			}
		}
	}
	for(i = 0; i < K; i++) D[i] = A[i][last];
}

void Dijkstra(int node, int *D)
{	
	
	for(int i = 1; i <= N; i++) D[i] = INF;
	D[node] = 0;
	
	q1.push(node); in[node] = true;
	
	while(!q1.empty())
	{	node = q1.top(); q1.pop();
		in[node] = false;
		
		for(it k = graph[node].begin(); k != graph[node].end(); k++)
			if(D[k->first] > D[node] + k->second)
			{	D[k->first] = D[node] + k->second;
				
				if(!in[k->first])
				{	in[k->first] = true;
					q1.push(k->first);
				}
			}
	}
}
	

int main()
{	int i, j, x, y, z;
	int ans = INF;

	f>>N>>M;
	
	f>>K;
	for(i = 0; i < K; i++)
	{	f>>kloc[i];
		isk[kloc[i]] = true;
		last = last | 1<<i;
	}
	for(i = 1; i <= M; i++)
	{	f>>x>>y>>z;
		
		graph[x].push_back(make_pair(y, z));
		graph[y].push_back(make_pair(x, z));
	}
	
	for(i = 0; i < K; i++)
	{	cmp1::row = kroad[i];
		Dijkstra(kloc[i], kroad[i]);
	}
	
	cmp1::row = kroad[16];
	Dijkstra(1, kroad[16]);
	
	for(i = 0; i < K; i++)
		for(j = i + 1; j < K; j++)
			kgraph[i][j] = kgraph[j][i] = kroad[i][kloc[j]];
	
	for(i = 0; i < K; i++)
		Dijkstra_exp(i, kans[i]);
	
	if(K == 0) ans = kroad[16][N];
	
	for(i = 0; i < K; i++)
		for(j = 0; j < K; j++)
			ans = min(ans, kroad[i][1] + kans[i][j] + kroad[j][N]);
		
	
	g<<ans;
	
	f.close();
	g.close();
	return 0;
}