Cod sursa(job #997724)

Utilizator gabrielinelusGabriel-Robert Inelus gabrielinelus Data 14 septembrie 2013 19:48:30
Problema Ubuntzei Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.97 kb
#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;//bagam si nodul de start in lista oraselor prin care trecem
    v[++K+1]=N;
    for(int i=2;i<=K;++i)fscanf(f,"%d",&v[i]);//cele k localitati prin care tre sa trec
    ++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));
    }
}

struct cmp{
    bool operator()(const pair<int,int> A,const pair<int,int> B)const
    {
        return A.second > B.second;
    }
};

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();
        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;
                Q.push(it->first);
            }
    }
}
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;//starea initiala C[i][j] - costul minim al unui
                //lanti H care trece prin nodurile din maska I si se termina in J
    for(i = 1; i < (1 << K) ; ++i) // luam toate mastile
        for(j = 0; j < K; ++j) // luam toate nodurile
            if( i & (1<<j) )// daca nodul j apare in maska
                for(it=G[j].begin(); it !=G[j].end();++it)//luam toti vecinii lui J
                    if(i & (1<<(*it)))//daca vecinul apare si el in maska , presupunem ca venim din el si optimizam
                        C[i][j]=min(C[i][j], C[i ^ (1<<j)][*it] + cost[*it][j]);// optim daca se poate
    int answer=C[(1<<K)-1][K-1];//in alte cuvinte , raspunsul se afla in maska completa si pe pozitia K-1 adica ultimul nod din V
    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);//dijkstra(v[i],i);
    make_newgraph();
    solve();
    return 0;
}