Pagini recente » Cod sursa (job #2592245) | Cod sursa (job #914439) | Cod sursa (job #2464798) | Cod sursa (job #56874) | Cod sursa (job #1592407)
#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);
}
}
}
}
}