Cod sursa(job #1594245)

Utilizator BogdanisarBurcea Bogdan Madalin Bogdanisar Data 9 februarie 2016 12:21:57
Problema Ubuntzei Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.81 kb
#include<iostream>
#include<fstream>
#include<cmath>
#include<algorithm>
#include<vector>
#include<bitset>
#include<cstring>
#include<queue>
#include<stack>

#define ull unsigned long long
#define ll long long
#define pb push_back
#define FOR(a,b,c) for (int a=b;a<=c; ++a)
#define ROF(a,b,c) for (int a=b;a>=c; --a)
#define Nmax 2100
#define Kmax 20
#define inf 1900900900

using namespace std;
ifstream f("ubuntzei.in");
ofstream g("ubuntzei.out");
int N,M,K;
int d[Nmax],ord_oras[Nmax],dist[Kmax][Kmax],dp[1<<Kmax][Kmax];
// d[i]=distanta de la un nod sursa la nodul i dupa o iterare a algoritmului dijkstra
// ord_oras[i]=numarul de ordine al nodului i in noul graf
// dist[i][j]=distanta de la nodul i la nodul j in noul graf
// dp[i][j]=distanta minima de la nodul sursa la nodul j de masca i in noul graf
vector<int> orase;
// vector ce retine orasele in care locuiesc prietenii ubuntzeilor

struct elem2 {
    int x,cost;
};
vector<elem2> edge[Nmax]; // edge[i]=lista nodurilor adiacente nodului i
priority_queue<elem2> heap; // heap pentru dijkstra

bool operator <(const elem2 a, const elem2 b) {
    return a.cost>b.cost;
}

void dijkstra(int);

int main()
{
    f>>N>>M>>K;
    const int sursa=1;
    const int dest=N;
    orase.pb(sursa);
    ord_oras[sursa]=orase.size()-1;
    FOR (i,1,K) {
        int x;
        f>>x;
        orase.pb(x);
        ord_oras[x]=orase.size()-1;
    }
    orase.pb(dest);
    ord_oras[dest]=orase.size()-1;
    FOR (i,1,M) {
        int x,y,cost;
        f>>x>>y>>cost;
        elem2 A;
        A.x=y;
        A.cost=cost;
        edge[x].pb(A);
        A.x=x;
        edge[y].pb(A);
    }
    dijkstra(sursa);
    if (!K) {
        g<<d[dest];
        return 0;
    }
    // se va crea un graf nou, format din sursa, destinatie si orasele ce contin prieteni
    vector<int>::iterator it;
    for (it=orase.begin(),++it;it<orase.end();++it) {
        dist[ord_oras[sursa]][ord_oras[*it]]=d[*it];
    }
    for (it=orase.begin(),++it;it<orase.end()-1;++it) {
        dijkstra(*it);
        vector<int>::iterator vecin;
        for (vecin=orase.begin();vecin<orase.end();++vecin) {
            if ((*it)!=(*vecin)) {
                dist[ord_oras[*it]][ord_oras[*vecin]]=d[*vecin];
            }
        }
    }
    // programare dinamica
    for (int i=1;i<(1<<orase.size());++i) {
        int ok=0;
        for (int j=0;j<orase.size();++j) {
            if (i==(1<<j)) {
                dp[i][j]=dist[ord_oras[sursa]][j];
                ok=1;
                break;
            }
        }
        if (ok) {
            continue;
        }
        for (int j=0;j<orase.size();++j) {
            dp[i][j]=inf;
            if (i & (1<<j)) {
                for (int k=0;k<orase.size();++k) {
                    if (j!=k && (i & (1<<k))) {
                        if (dp[i][j]>dp[i-(1<<j)][k]+dist[k][j]) {
                            dp[i][j]=dp[i-(1<<j)][k]+dist[k][j];
                        }
                    }
                }
            }
        }
    }
    g<<dp[(1<<orase.size())-1][ord_oras[dest]];
    f.close();g.close();
    return 0;
}

void dijkstra(int src) {
    FOR (i,1,N) {
        d[i]=inf;
    }
    d[src]=0;
    elem2 A;
    A.x=src;
    A.cost=0;
    heap.push(A);
    while (!heap.empty()) {
        A=heap.top();
        heap.pop();
        int nod=A.x;
        int cost=A.cost;
        if (d[nod]<cost) {
            continue;
        }
        vector<elem2>::iterator it;
        for (it=edge[nod].begin();it<edge[nod].end();++it) {
            int vecin=(*it).x;
            if (d[vecin]>d[nod]+(*it).cost) {
                d[vecin]=d[nod]+(*it).cost;
                A.x=vecin;
                A.cost=d[vecin];
                heap.push(A);
            }
        }
    }
}