Cod sursa(job #1592407)

Utilizator BogdanisarBurcea Bogdan Madalin Bogdanisar Data 7 februarie 2016 16:34:26
Problema Ubuntzei Scor 75
Compilator cpp Status done
Runda Arhiva de probleme Marime 5.18 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 2061109567

using namespace std;
ifstream f("ubuntzei.in");
ofstream g("ubuntzei.out");
int N,M,K;
int ord_oras[Nmax],d[Nmax],dist[Kmax][1<<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 sursa la nodul i cu masca j in graful nou
vector<int> orase; // vector ce retine orasele in care locuiesc prietenii ubuntzeilor
bitset<Nmax> prieten; // prieten[i]=1 daca in orasul i locuieste un prieten

struct elem2 {
    int y,cost;
};
vector<elem2> edge[Nmax]; // edge[i]=lista nodurilor adiacente nodului i
vector<elem2> edgeK[Kmax]; // edgeK[i]=lista nodurilor adiacente nodului i in graful nou
priority_queue<elem2> pQ; // heap pentru dijkstra

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

struct elem3 {
    int cost,nod,masca;
};
priority_queue<elem3> pQk; // heap pentru dijkstra

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

void dijkstra(int);
void dijkstraK(int);

int main()
{
    f>>N>>M>>K;
    const int sursa=1;
    const int dest=N;
    FOR (i,1,K) {
        int x;
        f>>x;
        orase.pb(x);
        ord_oras[x]=orase.size()-1;
        prieten.set(x,1);
    }
    orase.pb(sursa);ord_oras[sursa]=orase.size()-1;prieten.set(sursa,1);
    orase.pb(dest);ord_oras[dest]=orase.size()-1;prieten.set(dest,1);
    FOR (i,1,M) {
        int x,y,cost;
        f>>x>>y>>cost;
        elem2 A;
        A.y=y;
        A.cost=cost;
        edge[x].pb(A);
        A.y=x;
        edge[y].pb(A);
    }
    dijkstra(sursa);
    if (!K) {
        g<<d[dest]<<'\n';
    }
    else { // se va creea un graf nou ce contine doar sursa, destinatia si nodurile in care locuieste un prieten
        FOR (i,2,N) { // se actualizeaza muchiile pentru nodul sursa in graful nou
            if (prieten.test(i)) {
                elem2 A;
                A.y=ord_oras[i];
                A.cost=d[i];
                edgeK[ord_oras[sursa]].pb(A);
            }
        }
        vector<int>::iterator it;
        for (it=orase.begin();it<orase.end();++it) { // se actualizeaza muchiile pentru fiecare nod in graful nou
            if ((*it)!=sursa && (*it)!=dest) {
                dijkstra(*it);
                vector<int>::iterator it2;
                for (it2=orase.begin();it2<orase.end();++it2) {
                    //cout<<(*it2)<<'\n';
                    if ((*it)!=(*it2)) {
                        elem2 A;
                        A.y=ord_oras[*it2];
                        A.cost=d[*it2];
                        edgeK[ord_oras[*it]].pb(A);
                    }
                }
            }
        }
        dijkstraK(ord_oras[sursa]); // se face dijkstra intr-un graf in care fiecare nod e determinat de un nr si o masca de biti ce reprezinta nodurile vizitate pana atunci
        g<<dist[orase.size()-1][(1 << orase.size() ) - 1];
    }
    f.close();g.close();
    return 0;
}


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

void dijkstraK(int sursa) {
    FOR (i,0,orase.size()-1) {
        FOR (j,1,1<<orase.size()) {
            dist[i][j]=inf;
        }
    }
    dist[sursa][1<<(sursa)]=0;
    elem3 A;
    A.cost=0;
    A.nod=sursa;
    A.masca=(1<<(sursa));
    pQk.push(A);
    while (!pQk.empty()) {
        elem3 A=pQk.top();
        pQk.pop();
        int cost=A.cost;
        int nod=A.nod;
        int masca=A.masca;
        if (dist[nod][masca]<cost) {
            continue;
        }
        vector<elem2>::iterator it;
        for (it=edgeK[nod].begin();it<edgeK[nod].end();++it) {
            int vecin=(*it).y;
            if (!(masca&( 1<<(vecin)) ) ) {
                int masca_noua=masca | (1<<(vecin));
                if (dist[vecin][masca_noua]>dist[nod][masca]+(*it).cost) {
                    dist[vecin][masca_noua]=dist[nod][masca]+(*it).cost;
                    elem3 B;
                    B.cost=dist[vecin][masca_noua];
                    B.nod=vecin;
                    B.masca=masca_noua;
                    pQk.push(B);
                }
            }
        }
    }
}