知识点总结

最小瓶颈路

在最小生成树的基础上倍增处理下边权最大值就行

斯坦纳树

就是一个状压dp: dp[i][state]dp[i][state]表示以i为根,指定集合中的点的连通状态为state的生成树的最小总权值 转移方程有两种: 1、枚举子集: dp[i][state]=min(dp[i][state],dp[i][sub]+dp[i][statesub])dp[i][state] = min(dp[i][state], dp[i][sub] + dp[i][state - sub]) 枚举子集的方法:

1
for(sub=(state-1)&state;sub;sub=(sub-1)&state)

2、松弛操作(i到j有边相连) dp[i][state]=min(dp[i][state],dp[j][state]+W[i][j])dp[i][state]=min(dp[i][state], dp[j][state]+W[i][j])

最小树形图

最小乘积生成树(这篇有图,比较清晰)

Problems

Codeforces 733F Drivers Dissatisfaction(最小生成树+LCA)

Codeforces 733F Drivers Dissatisfaction(最小生成树+LCA)

BZOJ3732 Network(最小瓶颈路)

最小瓶颈路模板

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
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
#include <bits/stdc++.h>

using namespace std;

const int Maxn = 150000 + 10, Maxm = 600000 + 100;

struct node
{
int x, y, z;
}A[Maxn];

inline int cmp (node a, node b)
{
return a.z < b.z;
}

int N, M;
int e, Begin[Maxn], To[Maxm], Next[Maxm], W[Maxm];
int anc[Maxn][21], Max[Maxn][21];
int fa[Maxn], deep[Maxn];

inline void add_edge (int x, int y, int z)
{
To[++e] = y;
Next[e] = Begin[x];
Begin[x] = e;
W[e] = z;
}

inline int find (int x)
{
return fa[x] == x ? x : fa[x] = find(fa[x]);
}

inline void dfs (int x)
{
for (int i = 1; i <= 20; ++i) anc[x][i] = anc[anc[x][i - 1]][i - 1], Max[x][i] = max(Max[x][i - 1], Max[anc[x][i - 1]][i - 1]);
for (int i = Begin[x]; i; i = Next[i])
{
int y = To[i];
if (y == anc[x][0]) continue;
anc[y][0] = x;
Max[y][0] = W[i];
deep[y] = deep[x] + 1;
dfs(y);
}
}

inline int Lca (int x, int y)
{
int Ans = 0;
if (deep[x] < deep[y]) swap(x, y);
for (int i = 20; i >= 0; --i)
if (deep[anc[x][i]] >= deep[y])
Ans = max(Ans, Max[x][i]), x = anc[x][i];
if (x == y) return Ans;

for (int i = 20; i >= 0; --i)
if (anc[x][i] != anc[y][i])
Ans = max(Ans, max(Max[x][i], Max[y][i])), x = anc[x][i], y = anc[y][i];

Ans = max(Ans, max(Max[x][0], Max[y][0]));
return Ans;
}

int main()
{
#ifdef hk_cnyali
freopen("A.in", "r", stdin);
freopen("A.out", "w", stdout);
#endif
int K;
scanf("%d%d%d", &N, &M, &K);
for (int i = 1; i <= N; ++i) fa[i] = i;
for (int i = 1; i <= M; ++i)
scanf("%d%d%d", &A[i].x, &A[i].y, &A[i].z);
sort(A + 1, A + M + 1, cmp);

int cnt = 0;
for (int i = 1; i <= M; ++i)
{
int fx = find(A[i].x), fy = find(A[i].y);
if (fx == fy) continue;
add_edge (A[i].x, A[i].y, A[i].z);
add_edge (A[i].y, A[i].x, A[i].z);
// add_edge (fx, fy, A[i].z);
// add_edge (fy, fx, A[i].z);
fa[fy] = fx;
++cnt;
if (cnt == N - 1) break;
}

dfs(1);

while (K--)
{
int x, y;
scanf("%d%d", &x, &y);
printf("%d\n", Lca(x, y));
}
return 0;
}

Hdu3311 Dig the Wells(斯坦纳树+状压dp+SPFA)

Hdu3311 Dig the Wells(斯坦纳树+状压dp+SPFA)

Hdu4085 Peach Blossom Spring(斯坦纳树)

Hdu4085 Peach Blossom Spring(斯坦纳树)

Hdu4966 GGS-DDU (最小树形图/朱刘算法)

Hdu4966 GGS-DDU (最小树形图/朱刘算法)

BZOJ2395 Timeismoney(最小乘积生成树)

BZOJ2395 Timeismoney(最小乘积生成树)

Hdu5697 刷题计划(最小乘积生成树)

Hdu5697 刷题计划(最小乘积生成树)