[JOISC 2016 Day3 T3]「電報」基环树 + 拓扑判环

题目要求使用最小代价将给定的基环树构建成强连通图。每个点的出度为1,需要找到正确断边并复活某些边的方法,使得每个点都在同一个环中。通过拓扑排序和断边策略,计算断边和复活边的总成本,从而得到最小花费。
摘要由CSDN通过智能技术生成

题目描述

友情链接:https://loj.ac/problem/2737
题目描述
题目译自 JOISC 2016 Day3 T3「 電報
给出 n 个点,每个点的出度均为 1,给出这 n 个点初始指向的点Ai ,和改变这个点指向的目标所需要的价值 Ci
求让所有点强连通的最小花费。

输入格式
第一行输入一个数 n 表示点的个数。
之后的 n 行每行两个数 Ai,Ci 表示第 i 个点指向第 Ai 个点,更改该点指向的点花费为 Ci

输出格式
共一行,为让所有点强连通的最小花费。

样例输入输出

Sample Input 1
4
2 2
1 4
1 3
3 1
Sample Output 1
4

Sample Input 2
4
2 2
1 6
1 3
3 1
Sample Output 2
5

Sample Input 3
4
2 2
1 3
4 2
3 3
Sample Input 3
4

Sample Input 4
3
2 1
3 1
1 1
Sample Output 4
0

题解

(讲的有点混乱,理解一下。。。)
看了看题目所求,又看了看输入格式,然后发现,想要形成一个强连通,那不是要形成一个环吗?!!
既然如此,那么我们就可以开始进一步思考了,
对于任意一个图而言,我们都可以将它拆分成几个不同的部分,这些部分的结构只能是环(单独的一个点也算作是环)或者是树,因此,这个图是一个基环树
在这里插入图片描述
那么, 为了能让一堆基环树连成一个环,首先就是要断边,那么断哪些边捏??
接下来,我们进行分类讨论:

  • 对于任意一个环上的点,我们需要让它只存在于本环,不存在于其它树(可以想到,它只会存在于一个环)
  • 对于任意一棵树上的点,我们需要让它只存在于本树,与环不再有任何瓜葛。。。

知道了该怎么断边的断边的效果,就该思考怎么断掉这些边了。
(盯着上面那副图。。。)

  • 对于第一种情况,我们以节点2为例:我们需要断掉 5到2的边 以及 6到2的边 ,使节点2只存在于环中,节点5和节点6成为一条独立的链(一个点也是链)
    简单点说,就是需要断掉环上点与树上点相连的边
  • 对于第二种情况,我们以节点9为例:为了使它只存在于一条链当中,我们需要断掉它与节点1相连的边,成为独立的一个点(这图画得不太好,理解就好);如果它与其它非环上的点还有边相连,那么也需断掉多余的边,使每个节点有且仅有一条入边(题目保证了它只会有一条出边)
    一言以毕之,树上点只能保存一条入边,多余的边都要删掉

接下来,我们继续思考它们的贡献
(还是上面那幅图。。。还是相似的分类讨论)

  • 对于节点2而言,我们需要将除了3到2的边和2到1的边留下,其它的都需要街道其它节点,因此,我们需要加上修改这两条边的贡献;
    简而言之,除了与本环上点相连的边,都需要破掉,即累加这些边的贡献
  • 对于节点9而言,它需要破掉指向节点1的边(在判断节点1时会被破掉,但判断节点9时不会有影响)
    总的来说,就是要破掉多余的边,使之只剩一条入边,一条出边(或是单独一个点)

破完边之后,又出现了一个新问题:
这些破掉的边,最后会指向哪个节点?会不会就是原本指向的节点?
完全有可能!
因此,我们需要思考,“复活”一些边,使之成为一个环。
根据最优策略,我们需要复活消耗最高的那些边,才能使的答案花费最小。
至此,代码就可以出炉了

参考代码

#include <cstdio>
#include <iostream>
#include <vector>
#include <queue>
using namespace std;
#define INf 0x7f7f7f7f

const int N = 1e5;
int n, nxt[N + 5], cost_[N + 5], in[N + 5],<
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值