斯坦纳树(Steiner Tree)
#include <cstdio>
#include <climits>
#include <queue>
#include <algorithm>
const int MAXN = 50005;
const int MAXM = 300005;
const int MAXD = 5;
struct Edge;
struct Node {
Edge *e;
bool vis[1 << MAXD];
long long f[1 << MAXD];
} N[MAXN];
struct Edge {
Node *u, *v;
Edge *next;
int w;
Edge() {}
Edge(Node *u, Node *v, int w) : u(u), v(v), w(w), next(u->e) {}
} _pool[MAXM << 1], *_curr = _pool;
void addEdge(int u, int v, int w) {
N[u].e = new (_curr++) Edge(&N[u], &N[v], w);
N[v].e = new (_curr++) Edge(&N[v], &N[u], w);
}
namespace Dijkstra {
struct HeapNode {
Node *u;
int s;
long long dist;
HeapNode(Node *u, int s, long long dist) : u(u), s(s), dist(dist) {}
bool operator<(const HeapNode &rhs) const {
return dist > rhs.dist;
}
};
std::priority_queue<HeapNode> q;
void dijkstra() {
while (!q.empty()) {
Node *u = q.top().u;
int s = q.top().s;
q.pop();
if (u->vis[s]) continue;
u->vis[s] = true;
for (Edge *e = u->e; e; e = e->next) {
if (e->v->f[s] > u->f[s] + e->w) {
e->v->f[s] = u->f[s] + e->w;
q.emplace(e->v, s, e->v->f[s]);
}
}
}
}
void init(int n, int d) {
for (int i = 1; i <= n; i++) for (int s = 0; s < 1 << d; s++) {
N[i].f[s] = LLONG_MAX >> 1ll;
N[i].vis[s] = false;
}
while (!q.empty()) q.pop();
}
}
long long steiner(int n, int *p, int d) {
Dijkstra::init(n, d);
for (int i = 0; i < d; i++) N[p[i]].f[1 << i] = 0;
for (int S = 0; S < 1 << d; S++) {
for (int s = (S - 1) & S; s; s = (s - 1) & S)
for (int i = 1; i <= n; i++) N[i].f[S] = std::min(N[i].f[S], N[i].f[s] + N[i].f[S ^ s]);
for (int i = 1; i <= n; i++) if (N[i].f[S] < LLONG_MAX >> 1ll) Dijkstra::q.emplace(&N[i], S, N[i].f[S]);
Dijkstra::dijkstra();
}
long long res = LLONG_MAX;
for (int i = 1; i <= n; i++) res = std::min(res, N[i].f[(1 << d) - 1]);
return res;
}
int main() {
int n, m, d;
scanf("%d %d %d", &n, &m, &d);
for (int i = 0, u, v, w; i < m; i++) {
scanf("%d %d %d", &u, &v, &w);
addEdge(u, v, w);
}
static int p[MAXN];
for (int i = 0; i < d; i++) scanf("%d", &p[i]);
long long ans = steiner(n, p, d);
printf("%lld\n", ans);
return 0;
}