Cod sursa(job #1161046)

Utilizator BeilandArnoldArnold Beiland BeilandArnold Data 30 martie 2014 23:12:11
Problema Ubuntzei Scor 20
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.27 kb
#include <fstream>
#include <utility>
#include <vector>
#include <list>
#include <queue>
#include <limits>

const unsigned INF = std::numeric_limits<unsigned>::max()/4-5;

typedef std::pair<unsigned, unsigned> PUU;
typedef std::pair<unsigned, PUU> PUP;


inline void Dijkstra_normal(std::vector<unsigned> &Dist, const unsigned &start, const unsigned &N,
							const std::vector< std::list<PUU> > &Adj);

inline unsigned Dijkstra_modif(const unsigned &n,
							   const std::vector< std::list<PUU> > &Adj,
							   const std::vector< unsigned > &subsetmask);


int main(){
	std::ifstream fin("ubuntzei.in");
	std::ofstream fout("ubuntzei.out");

	unsigned N,M,K;
	fin>>N>>M>>K;


	std::vector< unsigned > subsetmask(N+1,0);
	std::vector< unsigned > subsetind(N+1,0);
	std::vector< unsigned > subsetmember(K+3);
	subsetind[1]=1; subsetind[N]=K+2;
	subsetmember[1]=1; subsetmember[K+2]=N;
	for(unsigned i=0;i<K;++i){
		unsigned x; fin>>x;
		subsetmask[x]=1<<i;
		subsetind[x]=i+2;
		subsetmember[i+2]=x;
	}

	std::vector< std::list<PUU> > Adj(N+1);

	for(unsigned i=0;i<M;++i){
		unsigned x,y,c; fin>>x>>y>>c;
		Adj[x].push_back(PUU(y,c));
		Adj[y].push_back(PUU(x,c));
	}

	std::vector< std::list<PUU> > NewAdj(N+1);

	std::vector<unsigned> Dist(N+1);
	Dijkstra_normal(Dist,1,N,Adj);

	if(K==0){
		fout<<Dist[N]<<'\n';
	}
	else{
		for(unsigned i=2;i<=N;++i) if(subsetind[i]!=0) NewAdj[1].push_back(PUU(subsetind[i],Dist[i]));

		for(unsigned i=2;i<=K+2;++i){
			Dijkstra_normal(Dist,subsetmember[i],N,Adj);

			for(unsigned j=1;j<=N;++j) if(subsetind[j]!=0&&j!=subsetmember[i])
				NewAdj[i].push_back(PUU(subsetind[j],Dist[j]));
		}

		fout<<Dijkstra_modif(K+2,NewAdj,subsetmask)<<'\n';
	}
}

inline void Dijkstra_normal(std::vector<unsigned> &dist, const unsigned &start, const unsigned &N,
							const std::vector< std::list<PUU> > &Adj){
	dist.assign(N+1,INF);
	std::vector<bool> visited(N+1,false);

	std::priority_queue<PUU,std::vector<PUU>,std::greater<PUU> > pq;
	dist[start]=0; pq.push(PUU(0,start));

	while(!pq.empty()){
		unsigned cdist=pq.top().first, cnod=pq.top().second;
		pq.pop(); visited[cnod]=true;

		if(dist[cnod]==cdist)
			for(auto it=Adj[cnod].begin();it!=Adj[cnod].end();++it)
				if((!visited[it->first] )&& dist[it->first]>cdist+it->second){
					dist[it->first]=cdist+it->second;
					pq.push(PUU(dist[it->first],it->first));
				}
	}
}

inline unsigned Dijkstra_modif(const unsigned &n,
							   const std::vector< std::list<PUU> > &Adj,
							   const std::vector< unsigned > &subsetmask){
	std::vector< std::vector<unsigned> > dist(n+1,std::vector<unsigned>(1<<(n-2),INF));
	std::vector< std::vector<bool> > visited(n+1,std::vector<bool>(1<<(n-2),false));

	std::priority_queue<PUP,std::vector<PUP>,std::greater<PUP> > pq;
	pq.push(PUP(0,PUU(1,0))); dist[1][0]=0;

	while(!pq.empty()){
		unsigned cdist=pq.top().first, cnod=pq.top().second.first, cset=pq.top().second.second;
		pq.pop(); visited[cnod][cset]=true;

		if(cdist==dist[cnod][cset]){
			for(auto it=Adj[cnod].begin();it!=Adj[cnod].end();++it){
				unsigned ngb=it->first, newset=cset|subsetmask[cnod];

				if(!visited[ngb][newset] && dist[ngb][newset]>dist[cnod][cset]+it->second ){
					dist[ngb][newset] = dist[cnod][cset] + it->second;
					pq.push(PUP( dist[ngb][newset], PUU(ngb,newset) ));
				}
			}
		}
	}

	return dist[n][(1<<(n-2))-1];
}