Cod sursa(job #697074)

Utilizator andunhillMacarescu Sebastian andunhill Data 28 februarie 2012 22:00:52
Problema Ubuntzei Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.83 kb
#include<fstream>
#include<iostream>
#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[32769][16];		//A[i][j] = cost of reaching j in  with mask i
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(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);
				}
			}
	}
}

bool bit(int nr, int x)
{	return (nr & (1<<x)) != 0;
}

int main()
{	int i, j, k, 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(j = 1; j < (1<<K); j++)
	{	
		for(i = 0; i < K; i++) if(j == (1<<i)) break;	//only one special node
		if(i < K && j == (1<<i)) 
		{	A[j][i] = kroad[16][kloc[i]];
			continue;
		}
		
		for(i = 0; i < K; i++)
		{	A[j][i] = INF;
			
			if(bit(j, i)) 
			{	cout<<"Bitul "<<i<<" apare in "<<j<<'\n';
				for(k = 0; k < K; k++)
				{	if(!bit(j, k) || i == k) continue;
					A[j][i] = min(A[j][i], A[j - (1<<i)][k] + kroad[k][kloc[i]]);
				}
			}
		}
	}
	
	if(K == 0) ans = kroad[16][N];
	
	for(i = 0; i < K; i++)
		ans = min(ans, A[last][i] + kroad[i][N]);
	
	g<<ans;
	
	f.close();
	g.close();
	return 0;
}