- 导语 -
打了几道模板题后我就勇敢的开始总结了.
- prim -
设已经拜访过的点集为(V), (dis)数组表示某点到(V)的最小距离(到其中任意点).
开始先向(V)中加入一个点, 先遍历找出(V)集合外(dis)最小的节点, 将这个节点加入(V), 然后用这个点更新(dis)数组.
重复以上过程 n-1 次.
时间复杂度(O(n^2)).
void prim() {
for (int i = 1; i <= n; ++i) {
DIS[i] = MP[i][1]; //MP表示两点间距离
VIS[i] = 0; //是否在集合内
PRE[i] = 1; //记录路径
}
PRE[1] = -1;
VIS[1] = 1;
for (int i = 2, k; i <= n; ++i) {
int minn = INF;
for (int j = 2; j <= n; ++j)
if (!VIS[j] && DIS[j] < minn) {
minn = DIS[j];
k = j;
}
tot += DIS[k];
VIS[k] = 1;
for (int j = 2; j <= n; ++j)
if (!VIS[j] && DIS[j] > MP[k][j]) {
DIS[j] = MP[k][j];
PRE[j] = k;
}
}
}
- krusksl -
将边从小到大排序, 依次插入.
每次插入前判断两端点是否联通(并查集), 如不连通才能插入.
成功插入(n-1)条边时((n)是点数)得到最小生成树.
时间复杂度(O(nlog(n)))((log(n))来自路径压缩).
void kruskal() {
for (int i = 1; i <= m; ++i) {
int xf = find(W[i].x), yf = find(W[i].y);
if (xf == yf) continue;
F[xf] = yf;
ans += W[i].v;
cnt ++;
if (cnt == n - 1) break;
}
}
- 最小瓶颈路 -
无向图中两点(u, v), 求两点间一条路径, 使路径上最大边的权值最小.
这条路径一定是在最小生成树上的, 因为求这样一条路我们需要像求最小生成树一样把边从小到大插入图中直到u, v联通, 而u, v联通时和整张图联通时u, v间的路径是一样的.
在询问少, 或点的数量少时, 我们可以直接暴力搜索得到答案.
uvalive 5713 Qin Shi Huang's National Road System
数据较大时, 我们需要把最小生成树正式地看做树用LCA来维护路径上的最大值.
uva 11354 Bond
- 生成树计数 -
- 曼哈顿距离最小生成树 -
- 最小有向生成树 -
即最小树形图.
poj 3164 Command Network(讲解)
uva 11865 Stream My Contest