斯坦纳树学习笔记
# 斯坦纳树
一个带权无向图上,令点集为关键点集,要联通所有关键点最小的代价。
该问题为公认的NPC问题,目前没有找到多项式复杂度的解!
以下算法只能解决关键点数较少时的问题
# 洛谷 P6192
给定一个包含 个结点和 条带权边的无向连通图 再给定包含 个结点的点集 选出 的子图 使得:
为连通图;
中所有边的权值和最小。
你只需要求出 中所有边的权值和。
保证给出的无向图连通,但可能存在重边和自环。
# 解法
显然最后得出的图一定是一颗树
记为以为根,联通点集的最小代价,则有一下两种转移方式
- ,缩小问题范围
遍历集合,对于每一个子集,先进行第一类转移,再进行第二类转移。
# AC代码
#include <bits/stdc++.h>
#define ll long long
#define ull unsigned long long
#define int128 __int128_t
#define Android ios::sync_with_stdio(false), cin.tie(NULL)
#define redirect_input freopen("./input.txt", "r", stdin);
#define redirect_output freopen("./output.txt", "w", stdout);
#define debug(s, r) std::cerr << #s << ": " << (s) << (r==0?' ':'\n')
#define pii pair<int, int>
#define sqr(x) ((x)*(x))
using namespace std;
const int inf = 0x3f3f3f3f;
const int maxn = 100 + 10;
int n, m, k;
int st[maxn];
int dp[(1<<10) + 100][maxn];
vector<pii> G[maxn];
void dijkstra(int s){
priority_queue<pii, vector<pii>, greater<pii> > que;
for(int i=1; i<=n; i++) {
if(dp[s][i] != inf) que.push({dp[s][i], i});
}
while(!que.empty()){
pii cur = que.top(); que.pop();
int u = cur.second;
if(dp[s][u] != cur.first) continue;
for(pii edge:G[u]){
int v = edge.first;
if(dp[s][v] > dp[s][u] + edge.second){
dp[s][v] = dp[s][u] + edge.second;
que.push({dp[s][v], v});
}
}
}
}
void solve(){
memset(dp, 0x3f, sizeof dp);
cin >> n >> m >> k;
for(int i=0, u, v, w; i<m; i++){
cin >> u >> v >> w;
G[u].push_back({v, w});
G[v].push_back({u, w});
}
for(int i=0; i<k; i++) cin >> st[i];
for(int i=0; i<k; i++)
dp[1<<i][st[i]] = 0;
for(int s=1; s<(1<<k); s++){
for(int subs = s&(s-1); subs; subs = s & (subs-1)){ // 第二类转移
for(int i=1; i<=n; i++){
dp[s][i] = min(dp[s][i], dp[subs][i] + dp[subs ^ s][i]);
}
}
dijkstra(s); // 第一类转移
}
cout << dp[(1<<k)-1][st[rand() % k]] << '\n';
}
signed main(){
Android;
solve();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
上次更新: 2021/02/24, 03:37:30