【C++心路历程30】(APIO2013)道路费用

本文讲述了C++编程解决一个关于道路费用和最大收入的问题。C国计划新建道路,首富皮特需要决定费用以最大化收入。问题涉及最小生成树和路径费用优化。文章介绍了三种算法思路,包括暴力枚举、二进制枚举和缩点算法,旨在找到最优的道路费用设置以获取最大收益。
摘要由CSDN通过智能技术生成

【问题描述】

  皮特现在是C国最富有的人。
  C国共有n个城市(用1~n 编号),现在这些城市由m条双向道路连接,其中城市1为首都。保证一个人从城市1出发,经过这些道路可以到达其他的任何一个城市。当然,所有的这些道路都是要收费的,使用道路i需要向该道路的所有者支付ci的费用。已知所有的ci互不相同。最近C国计划新建 条道路,毋庸置疑,当然是富豪皮特负责,因而新建的k条道路(也仅有这k条道路)是属于皮特的。
  皮特可以自行决定着k条道路的费用,并且皮特将在明天公布这些费用。两周以后,C国将在首都举行盛大的阅兵式,其中共有pi个参与者从城市i出发。大量的参与者将沿着这些道路前往首都。这些人只会沿着一个选出的道路集合行进,根据一个古老的习俗,这些道路将由最富有的人,也就是皮特指定,并且皮特将在后天公布选出的集合。同样根据这个习俗,皮特选出的道路集合必须使所有选出的道路的费用之和最小,并且仍要保证每个城市都可以经选出的道路到达首都。也就是说,选出的道路来自以费用作为相应边权的最小生成树。如果有多个这样的集合,皮特可以任选。
尽管皮特现在是首富,但他依旧想尽办法敛财。他希望通过控制属于他的 条道路的费用以及所选取的道路集合来使自己的收入最大化。他明白,他获得的收益并不只与指定的费用有关,也与通过这条道路的人数有关。准确的说,如果有p 个人经过费用为ci 的道路,那么道路所有者就会获得p*ci 的收入。注意,皮特的选择必须符合习俗。
  但是皮特并不够聪明,于是他来求助你。你现在需要做的就是计算皮特所能得到的最大收入!

【输入格式】

  第一行包含三个由空格隔开的正整数n,m,k 。
  接下来的m 行描述最开始的m 条道路。这ui,vi,ci 行每行包含三个空格隔开整数 ,表示在ui 和vi 之间有一条费用为ci 的双向道路。保证1<=ui,vi<=n ,且当i!=j 时,ci!=cj 。
  接下来k 行描述k 条新道路。每行包含两个空格隔开的整数ai,bi ,表示有一条连接城市ai,bi 的新道路,其费用由皮特决定。保证1<=ai,ni<=n 。
  最后一行包含n 个空格隔开的整数,其中第i 个表示pi ,即城市i 中要前往首都的人数。
保证在任意两个城市之间,最多有一条道路连接(包括新建的道路)。

【输出格式】

  输出只有一行,包含一个整数,表示皮特能获得的最大收入。

【输入样例】

5 5 1
3 5 2
1 2 3
2 3 5
2 4 4
4 3 6
1 3
10 20 30 40 50

【输出样例】

400

【样例解释】

  皮特应将新道路(1,3) 的费用设为5 。在这个费用下,他可以选择道路(3,5)、(1,3)、(2,4) 和 (1,3)。可以以证明,这样的收入是最大的。

大意:n个点,点权为Pi,m条边的图,新建不超过k条道路,每条费用由你决定,一条道路收取的费用为通过人数*边上的费用。但前提是所选边构成MST.在所有人都要去1号点集合的情况下,求你的最大收益。  
感觉题解网上其他地方似乎已经很多啦。所以就大概说一下。

暴力枚举1(期望得分20,过k=1的数据)(O(k*m))
将k条边逐一加入到原图最小生成树中,替换原图上的最大边。在k>1时不能保证正确。
核心代码:

`LL LCA(int u,int v)
{
    int maxtt=-1;
    if(dep[u]<dep[v]) 
    {
        swap(u,v);swap(xj[1].u,xj[1].v);
    }
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值