Cod sursa(job #997760)
#include <cstdio>
#include <vector>
#include <algorithm>
#include <queue>
#include <bitset>
#include <cstring>
FILE *f=fopen("ubuntzei.in","r");
FILE *g=fopen("ubuntzei.out","w");
using namespace std;
const int INF = 0x3f3f3f3f;
const int Nmax = 2005,Mmax=10005,Kmax=17;
int N,M,K,v[Kmax+10];
int C[(1<<Kmax)+10][Kmax],cost[Kmax+10][Kmax+10];
int D[Kmax][Nmax];
bitset<Nmax>used[Kmax+10];
vector<int>G[Kmax+10];
vector<pair<int,int> > lv[Nmax];
void get_graph()
{
fscanf(f,"%d%d%d",&N,&M,&K);
v[1]=1;v[++K+1]=N;
for(int i=2;i<=K;++i)fscanf(f,"%d",&v[i]);
++K;
sort(v+1,v+K+1);
int a,b,c;
for(int i=1;i<=M;++i)
{
fscanf(f,"%d%d%d",&a,&b,&c);
lv[a].push_back(make_pair(b,c));
lv[b].push_back(make_pair(a,c));
}
}
void bellman_ford(int nodc,int lvl)
{
queue<int> Q;
vector<pair<int,int> > ::iterator it;
D[lvl][nodc]=0;
Q.push(nodc);
while(!Q.empty()){
nodc=Q.front();
Q.pop();
used[lvl][nodc]=false;
for(it=lv[nodc].begin();it!=lv[nodc].end();++it)
if(D[lvl][it->first] > D[lvl][nodc] + it->second){
D[lvl][it->first] = D[lvl][nodc] + it->second;
if(!used[lvl][it->first]){
Q.push(it->first);
used[lvl][it->first]=true;
}
}
}
}
void make_newgraph()// aici creeam noul graf ( complet ) in care
{ //trebuie sa determinam LANTUL hamiltonian de cost minim
memset(cost,INF,sizeof(cost));
for(int i=0;i<K;++i)
for(int j=i+1;j<K;++j)
if(i!=j){
G[j].push_back(i);
G[i].push_back(j);
cost[i][j]=cost[j][i]=D[i+1][v[j+1]];
}
}
void solve()
{
memset(C,INF,sizeof(C));
int i,j;
vector<int> :: iterator it;
C[1][0]=0;
for(i = 1; i < (1 << K) ; ++i)
for(j = 0; j < K; ++j)
if( i & (1<<j) )
for(it=G[j].begin(); it !=G[j].end();++it)
if(i & (1<<(*it)))
C[i][j]=min(C[i][j], C[i ^ (1<<j)][*it] + cost[*it][j]);
int answer=C[(1<<K)-1][K-1];
fprintf(g,"%d",answer);
}
int main()
{
get_graph();
memset(D,INF,sizeof(D));
for(int i=1;i<=K;++i)
bellman_ford(v[i],i);
make_newgraph();
solve();
return 0;
}