Cod sursa(job #949257)

Utilizator narcis_vsGemene Narcis - Gabriel narcis_vs Data 12 mai 2013 22:47:29
Problema Ubuntzei Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.8 kb
#include <cstdio>
#include <queue>
#include <cstring>

#define In "ubuntzei.in"
#define Out "ubuntzei.out"

#define Nmax 2000
#define Kmax 15
#define Inf 0x3f3f3f3f
#define min(a,b) ((a)<=(b)?(a):(b))

#define PAIR pair< int , int >
#define nod first
#define cost second
#define mp make_pair
#define pb push_back

using namespace std ;
int N, K, MAX_STARE;
int a[Kmax];//retine multimea celor k orase
int Dist[Kmax][Nmax];
///Dist[i][j] = distanta minima de la a[i] la j
int dp[Kmax][1<<Kmax];
///dp[i][j] = costul minim pentru a ajunge din nodul 0 in al i-lea oras
///vizitand nodurile care faca parte din multimea bitilor de 1 a alui j
vector< PAIR >Graf[Nmax];//graful initial
inline void Citire()
{
    int x,y,c,M,i;
    freopen(In,"r",stdin);
    freopen(Out,"w",stdout);
    scanf("%d %d %d",&N,&M,&K);
    for(i = 0;i < K; i++)
    {
        scanf("%d ",&a[i]);
        a[i]--;
    }
    while(M--)
    {
        scanf("%d %d %d",&x,&y,&c);
        x--,y--;
        Graf[x].pb(mp(y,c));
        Graf[y].pb(mp(x,c));
    }
    MAX_STARE = (1<<K)-1;//numarul cu exact K biti de 1
}
struct cmp
{
    bool operator () (const PAIR &A,const PAIR &B)
    {
        return A.cost > B.cost;
    }
};
inline void Dijkstra(int i,int nod)
{
    priority_queue< PAIR,vector< PAIR >,cmp >Q;
    Dist[i][nod] = 0;
    Q.push(mp(nod,0));
    PAIR act;
    while(!Q.empty())
    {
        act = Q.top();
        Q.pop();
        for(vector< PAIR >::iterator vec=Graf[act.nod].begin();vec!=Graf[act.nod].end();vec++)
            if(Dist[i][(*vec).nod] > Dist[i][act.nod]+(*vec).cost)
            {
                Dist[i][(*vec).nod] = Dist[i][act.nod]+(*vec).cost;
                Q.push(mp((*vec).nod, Dist[i][(*vec).nod]));
            }
    }
}
inline void Afisare()
{
    int i,sol = Inf;
    for(i = 0;i < K ;i++)
        sol = min(sol,dp[i][MAX_STARE] + Dist[i][N-1]);
    printf("%d\n",sol);
}
inline void Init()
{
    int i;
    memset(Dist,Inf,sizeof(Dist));
    memset(dp,Inf,sizeof (dp));
    for(i = 0;i < K ;i++)
        Dijkstra(i,a[i]);
    for(i = 0;i < K ;i++)
        dp[i][1<<i] = Dist[i][0];//distanta de la 0 la a[i] folosind multimea 2^i este dist[i][0]
}
int main()
{
    Citire();
    Init();
    int i,j,stare;
    if(K==0)
    {
        Dijkstra(0,0);
        printf("%d\n",Dist[0][N-1]);
        return 0;
    }
    for(stare = 1;stare <= MAX_STARE ;stare++)//pentru fiecare stare
        for(i = 0;i < K ;i++)
            if((stare & (1<<i))!=0)//procesam fiecare bit
                for(j = 0;j < K ;j++)//incercam sa venim din j
                    if(i!=j &&(stare & (1<<j))!=0)//acesta trebuie sa apartina multimii
                        dp[i][stare] = min(dp[i][stare],dp[j][stare-(1<<i)] + Dist[j][a[i]]);
    Afisare();
    return 0;
}