板子整理
如果不能保证,要加入stein树的点没有重复,
建议不要如板子里这么写,因为去重之后,不能确定点在vec里排第几位了,
当然可以魔改成不去重,但是处理时是st[it]=st[it] | endSt的写法
#include <bits/stdc++.h>
using namespace std;
#define pii pair <int, int>
#define fi first
#define se second
const int N = 32;
const int K = 10;//一般不超过15
int n, m;
vector <vector<pii>> G;
struct SteinerTree {
int st[N], dp[N][1 << K], endSt;
bool vis[N][1 << K];
queue <int> que;
//一共n个点 vec中的点是要被加入stein树里的
void init(int n, vector <int> &vec) {
sort(vec.begin(), vec.end());
vec.erase(unique(vec.begin(), vec.end()), vec.end());
memset(dp, -1, sizeof dp);
memset(vis, 0, sizeof vis);
memset(st, 0, sizeof st);
endSt = 1;
for (auto it : vec) {
st[it] = endSt;
endSt <<= 1;
}
for (int i = 1; i <= n; ++i) {
dp[i][st[i]] = 0;
}
}
void update(int &a, int x) {
a = (a > x || a == -1) ? x : a;
}
void SPFA(int state) {
while (!que.empty()) {
int u = que.front(); que.pop();
vis[u][state] = false;
for (auto it : G[u]) {
int v = it.fi, w = it.se, y = st[v] | state;
if (dp[v][y] == -1 || dp[v][y] > dp[u][state] + w) {
dp[v][y] = dp[u][state] + w;
if (y != state || vis[v][state])
continue;
vis[v][state] = true;
que.push(v);
}
}
}
}
int solve() {
for (int j = 1; j < endSt; ++j) {
for (int i = 1; i <= n; ++i) {
if (st[i] && (st[i] & j) == 0) continue;
for (int sub = (j - 1) & j; sub; sub = (sub - 1) & j) {
int x = st[i] | sub, y = st[i] | (j - sub);
if (dp[i][x] != -1 && dp[i][y] != -1) {
update(dp[i][j], dp[i][x] + dp[i][y]);
}
}
if (dp[i][j] != -1) {
que.push(i), vis[i][j] = true;
}
}
SPFA(j);
}
int res = 1e9;
for (int i = 1; i <= n; ++i) if (dp[i][endSt - 1] != -1) {
res = min(res, dp[i][endSt - 1]);
}
return res;
}
}ST;
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
while (cin >> n >> m)
{
G.clear();
G.resize(n + 1);
for (int i = 1, u, v, w; i <= m; ++i)
{
cin >> u >> v >> w;
G[u].push_back(pii(v, w));
G[v].push_back(pii(u, w));
}
vector<int>vec;
/*
向vec内放入要加入stein树的点集的编号
*/
ST.init(n, vec);
cout<<ST.solve()<<endl;
}
return 0;
}