Cod sursa(job #784503)

Utilizator visanrVisan Radu visanr Data 6 septembrie 2012 10:17:50
Problema Ubuntzei Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.46 kb
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;


#define pb push_back
#define mp make_pair
#define f first
#define s second
#define inf 0x3f3f3f3f
#define Kmax 15
#define Nmax 10010

int N, M, K, C[Kmax], X, Y, Cc;
vector<pair<int, int> > G[Nmax];
int distS[Nmax], path[Kmax][Nmax];
int dp[1 << Kmax][Kmax];
priority_queue<pair<int, int>, vector<pair<int, int> >, greater<pair<int, int> > > Q;


void Dijkstra(int node, int *ans)
{
     int i;
     vector<pair<int, int> > :: iterator it;
     for(i = 1; i <= N; i++)
           ans[i] = inf;
     ans[node] = 0;
     while(!Q.empty()) Q.pop();
     for(i = 1; i <= N; i++)
           Q.push(mp(ans[i], i));
     for(i = 1; i <= N; i++)
     {
           pair<int, int> now;
           now = Q.top(), Q.pop();
           if(ans[now.s] < now.f) continue;
           for(it = G[now.s].begin(); it != G[now.s].end(); ++it)
                  if(ans[it -> f] > ans[now.s] + it -> s)
                  {
                            ans[it -> f] = ans[now.s] + it -> s;
                            Q.push(mp(ans[it -> f], it -> f));
                  }
     }
}

int main()
{
    freopen("ubuntzei.in", "r", stdin);
    freopen("ubuntzei.out", "w", stdout);
    int i, j, k;
    scanf("%i %i %i", &N, &M, &K);
    for(i = 0; i < K; i++)
          scanf("%i", &C[i]);
    for(; M; M --)
    {
          scanf("%i %i %i", &X, &Y, &Cc);
          G[X].pb(mp(Y, Cc));
          G[Y].pb(mp(X, Cc));
    }
    Dijkstra(1, distS);
    if(K == 0) 
    {
         printf("%i\n", distS[N]);
         return 0;
    }
    for(i = 0; i < K; i++)
          Dijkstra(C[i], path[i]);
    for(i = 1; i < (1 << K); i++)
    {
          for(j = 0; j < K; j++)
                if(i == (1 << j))
                     break;
          if(j < K && i == (1 << j))
          {
               dp[i][j] = distS[C[j]];
               continue;
          }
          for(j = 0; j < K; j++)
          {
                dp[i][j] = inf;
                if(i & (1 << j))
                     for(k = 0; k < K; k++)
                           if(k != j && (i & (1 << k)))
                                dp[i][j] = min(dp[i][j], dp[i - (1 << j)][k] + path[k][C[j]]);
          }
    }
    int ans = inf;
    for(i = 0; i < K; i++)
          ans = min(ans, dp[(1 << K) - 1][i] + path[i][N]);
    printf("%i\n", ans);
    return 0;
}