斯坦纳树
经典题:HDU4085
// HDU-4085.cpp
#include <bits/stdc++.h>
using namespace std;
typedef pair<int, int> pii;
const int MAX_N = 55, MAX_K = 10, MAX_E = 2020, INF = 0x3f3f3f3f;
int T, n, m, k, head[MAX_N], current, bi[MAX_N], f[MAX_N][1 << MAX_K], dp[1 << MAX_K];
queue<pii> q;
bool vis[MAX_N][1 << MAX_K];
struct edge
{
int to, nxt, weight;
} edges[MAX_E];
void addpath(int src, int dst, int weight)
{
edges[current].to = dst, edges[current].nxt = head[src];
edges[current].weight = weight, head[src] = current++;
}
void spfa()
{
while (!q.empty())
{
int uid = q.front().first, stat = q.front().second;
q.pop(), vis[uid][stat] = false;
for (int i = head[uid]; i != -1; i = edges[i].nxt)
if (f[edges[i].to][stat] > f[uid][stat] + edges[i].weight)
{
f[edges[i].to][stat] = f[uid][stat] + edges[i].weight;
if (!vis[edges[i].to][stat])
vis[edges[i].to][stat] = true, q.push(make_pair(edges[i].to, stat));
}
}
}
bool check(int stat)
{
int acc = 0;
for (int i = 0; i < k; i++)
acc += ((stat >> i) & 1);
for (int i = k; i < 2 * k; i++)
acc -= ((stat >> i) & 1);
return acc == 0;
}
int main()
{
scanf("%d", &T);
while (T--)
{
memset(head, -1, sizeof(head)), current = 0;
scanf("%d%d%d", &n, &m, &k);
for (int i = 1, u, v, w; i <= m; i++)
scanf("%d%d%d", &u, &v, &w), addpath(u, v, w), addpath(v, u, w);
memset(bi, 0, sizeof(bi)), memset(f, 0x3f, sizeof(f));
for (int i = 1; i <= k; i++)
bi[i] = 1 << (i - 1), f[i][bi[i]] = 0;
for (int i = 1; i <= k; i++)
bi[n - k + i] = 1 << (k + i - 1), f[n - k + i][bi[n - k + i]] = 0;
for (int stat = 1; stat < (1 << (2 * k)); stat++)
{
for (int i = 1; i <= n; i++)
{
for (int sub = stat & (stat - 1); sub; sub = (sub - 1) & stat)
f[i][stat] = min(f[i][stat], f[i][stat ^ sub] + f[i][sub]);
if (f[i][stat] != INF)
q.push(make_pair(i, stat)), vis[i][stat] = true;
}
spfa();
}
memset(dp, 0x3f, sizeof(dp));
for (int stat = 0; stat < (1 << (2 * k)); stat++)
for (int i = 1; i <= n; i++)
dp[stat] = min(dp[stat], f[i][stat]);
for (int stat = 0; stat < (1 << (2 * k)); stat++)
for (int sub = (stat - 1) & stat; sub; sub = (sub - 1) & stat)
if (check(sub))
dp[stat] = min(dp[stat], dp[sub] + dp[stat ^ sub]);
if (dp[(1 << (2 * k)) - 1] != INF)
printf("%lld\n", dp[(1 << (2 * k)) - 1]);
else
puts("No solution");
}
return 0;
}