OI-wiki 图论部分

有简单的东西,也有一些奇怪的算法。

总结: 学好 Kruskal 就对了.

0. 一点前置习题

1. luoguP4047 [JSOI2010]部落划分

实际上就是 Kruskal 做最小生成树, 将图从 \(k\) 个连通块变成 \(k-1\) 个连通块时所连的那条边的长度.
因为做最小生成树的时候各个连通块必然都是树, 所以说这等价于所用的第 \(n-k+1\) 条边, 不用维护连通块个数了.

int used=0;
for(int i=1;i<=cnt;i++)
{
    int fu=find(e[i].u),fv=find(e[i].v);
    if(fu==fv)continue;
    merge(fu,fv);
    used++;
    if(used==n-k+1)
    {
        printf("%.2lf\n",sqrt(e[i].val));
        return 0;
    }
}

2. luoguP3101 [USACO14JAN]Ski Course Rating G

还是一个 Kruskal 的过程. 维护每个连通块里有几个起点, 每次合成的连通块的大小大于 \(T\), 这个连通块对答案的贡献就是连通块内点的数量乘上连接两个连通块的边权.
算完之后记得把连通块的起点个数清零, 不要算重复了.

for(int i=1;i<=cnt;i++)
{
    int fu=find(e[i].u),fv=find(e[i].v);
    if(fu==fv)continue;
    if(siz[fu]+siz[fv]>=t)
    {
        ans+=e[i].val*(scnt[fu]+scnt[fv]);
        scnt[fu]=scnt[fv]=0;
    }
    merge(fu,fv);
}

3. luoguP1967 [NOIP2013 提高组] 货车运输

如果这是个树上问题, 那我们随便就维护了.
但其实在图上也没有多难, 仍然是考虑 Kruskal 的过程, 我们发现只需要建出原图的最大生成树, 然后在最大生成树上做询问就行了.
(代码懒得写了, 大概可以参考下一题)

4. CF609E Minimum spanning tree for each edge

首先我们求出最小生成树. 容易发现, 对于每条非树边, 它对应的生成树上的路径上的每条边的权值都(非严格)大于这条非树边.
那这个问题其实也就变得简单了, 我们只需要把生成树上边权最大的边删掉, 加上当前这条边, 就得到了经过这条边的最小生成树.

(代码咕咕咕)

1. Boruvka 算法

首先我们先复习一下 Kruskal 算法和 Prim 算法。
Kruskal 算法:加边加边加边,并查集查询!
Prim 算法:像 Dijkstra 一样每次取到连通块距离最小的点就完事了。

Boruvka 算法就比较神奇了。它和 Prim 算法比较像,但是是多路增广。
具体流程如下:

  • 初始时每个点是一个连通块。
  • 我们每次选择每个连通块并加入连向其他连通块的边权最小的边。
  • 重复算法直到每个连通分量都成为一个连通块。

容易发现在我们将边严格排序后,连边是不会出现环的。(因为连接两个连通块的最短的边只有那一条)
实现时用并查集维护连通块,并且注意一条边连接完两个连通块后,另一个连通块就不要再用这条边连回原来的连通块了。

(代码不写了)

虽然说这个算法比较冷门,但它并不是完全没用的。看下面的题:

CF888G Xor-MST

(咕咕咕)

2. 最小生成树的唯一性

考虑 Kruskal 的过程. 容易发现, 如果有权值相同的边, 并且实际使用的边的数量和最多能使用的边的数量(即连接后不会和先前的边形成环的边的数量)不同, 最小生成树就是不唯一的. 换句话说, 我们换个顺序跑 Kruskal 就会得到不同的最小生成树.
然后就做完了(

(并没有例题)

3. 次小生成树

luoguP4180 [BJWC2010] 严格次小生成树

首先我们考虑非严格次小生成树怎么做.
容易发现次小生成树和原生成树最多只有一条边的差异.
具体地, 我们考虑用一条非树边来替换原来生成树上的边, 容易发现替换生成树上对应链的最大值即可.

上面的做法是非严格的, 因为有可能替换的边和这条非树边的长度相同.
要求严格次小生成树, 我们还是用相同的思路, 但是当替换的边和这条非树边的长度相同时, 我们选择用链上的严格次大值来替换, 这样就保证了求出的生成树是严格次小的.

(代码咕咕咕)

4. 瓶颈生成树和最小瓶颈路

瓶颈生成树是最大边权值最小的生成树.
容易发现最小生成树一定是瓶颈生成树. 否则我们将原来最小生成树的最长边删掉, 然后用瓶颈生成树中的某一条边(显然存在)连接两部分, 得到的生成树的边权和就会更小, 这就产生了矛盾.
当然瓶颈生成树并不一定是最小生成树.

\(u\)\(v\) 的最小瓶颈路定义为使得最大边权值最小的 \(u\)\(v\) 的路径.
同样有结论, 最小生成树上 \(u\)\(v\) 的路径一定是一条最小瓶颈路, 但是最小瓶颈路不一定是最小生成树上的路径.

总之, 瓶颈生成树和最小瓶颈路都不一定是唯一的, 但是它们的最大边的长度是唯一确定的, 可通过最小生成树求出.

(例题略)

5. Kruskal 重构树

6. 最小树形图

7. 最小直径生成树

原文地址:http://www.cnblogs.com/pjykk/p/16541855.html

1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长! 2. 分享目的仅供大家学习和交流,请务用于商业用途! 3. 如果你也有好源码或者教程,可以到用户中心发布,分享有积分奖励和额外收入! 4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解! 5. 如有链接无法下载、失效或广告,请联系管理员处理! 6. 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需! 7. 如遇到加密压缩包,默认解压密码为"gltf",如遇到无法解压的请联系管理员! 8. 因为资源和程序源码均为可复制品,所以不支持任何理由的退款兑现,请斟酌后支付下载 声明:如果标题没有注明"已测试"或者"测试可用"等字样的资源源码均未经过站长测试.特别注意没有标注的源码不保证任何可用性