https://www.acwing.com/problem/content/531/
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 12, M = 1 << N, INF = 0x3f3f3f3f;
int n, m;
int d[N][N], g[N][M];
int f[M][N];
int main()
{
scanf("%d%d", &n, &m);
memset(d, 0x3f, sizeof d);
for (int i = 0; i < n; i ++ ) d[i][i] = 0;
while (m -- )
{
int a, b, c;
scanf("%d%d%d", &a, &b, &c);
a --, b -- ;
d[a][b] = d[b][a] = min(d[a][b], c);
}
memset(g, 0x3f, sizeof g);
for (int i = 0; i < n; i ++ )
for (int j = 0; j < 1 << n; j ++ )
for (int k = 0; k < n; k ++ )
if (j >> k & 1)
g[i][j] = min(g[i][j], d[i][k]);
//預處理加速dp轉移
memset(f, 0x3f, sizeof f);
for (int i = 0; i < n; i ++ ) f[1 << i][0] = 0;//利用題目條件:初始道路免費
for (int i = 1; i < 1 << n; i ++ )
for (int j = i - 1 & i; j; j = j - 1 & i) // 列舉i的子集
{
int r = i ^ j, cost = 0;
for (int k = 0; k < n; k ++ )
if (j >> k & 1)
{
cost += g[k][r];
if (cost >= INF) break;
}
if (cost >= INF) continue;
for (int k = 1; k < n; k ++ )
f[i][k] = min(f[i][k], f[r][k - 1] + cost * k);
}
int res = INF;
for (int i = 0; i < n; i ++ )
res = min(res, f[(1 << n) - 1][i]);
printf("%d\n", res);
return 0;
}