Cod sursa(job #1800989)

Utilizator bogdan10bosBogdan Sitaru bogdan10bos Data 8 noiembrie 2016 15:25:43
Problema Ciclu hamiltonian de cost minim Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 1.54 kb
#include <bits/stdc++.h>

using namespace std;

int N, M, B;
int c[25][25];
int dp[300005][20];
int p2[300005];

vector <int> edg[25];

int main()
{
    freopen("hamilton.in", "r", stdin);
    freopen("hamilton.out", "w", stdout);

    scanf("%d%d", &N, &M);
    for(int i = 1; i <= M; i++)
    {
        int x, y, z;
        scanf("%d%d%d", &x, &y, &z);
        c[x][y] = z;
        if(x != N)  edg[y].push_back(x);
    }

    for(int i = 2; i < (1 << N); i++)
    {
        p2[i] = p2[i - 1];
        if( (2 << p2[i]) == i )
            p2[i]++;
    }

    N--;
    for(int i = 0; i < N; i++)
        if(c[N][i])
            dp[1 << i][i] = c[N][i];

    for(int msk = 1; msk < (1 << N); msk++)
    {
        if( !(msk & (msk - 1)) )    continue;
        int m = msk;
        while(m)
        {
            int lst = p2[m];
            m -= (1 << lst);

            dp[msk][lst] = 1 << 30;
            for(auto x: edg[lst])
                if( msk & (1 << x) )
                {
                    if(dp[msk ^ (1 << lst)][x])
                        dp[msk][lst] = min(dp[msk][lst], dp[msk ^ (1 << lst)][x] + c[x][lst]);
                }
            if(dp[msk][lst] == (1 << 30))
                dp[msk][lst] = 0;
        }
    }

    int ans = 1 << 30;
    for(auto x: edg[N])
        if(dp[(1 << N) - 1][x])
            ans = min(ans, dp[(1 << N) - 1][x] + c[x][N]);
    if(ans == (1 << 30))
    {
        printf("Nu exista solutie\n");
        return 0;
    }
    printf("%d\n", ans);

    return 0;
}