技术经验解读:【最小生成树】新的开始(newstart)解题报告

简介: 技术经验解读:【最小生成树】新的开始(newstart)解题报告

【题目描述】


发展采矿业当然首先得有矿井, 小FF花了上次探险获得的千分之一的财富请人在岛上挖了n口矿井, 但他似乎忘记考虑的矿井供电问题…… 为了保证电力的供应, 小FF想到了两种办法:


在这一口矿井上建立一个发电站,费用为v(发电站的输出功率可以供给任意多个矿井)。


将这口矿井与另外的已经有电力供应的矿井之间建立电网, 费用为p。小FF希望身为”NewBe_One" 计划首席工程师的你帮他想出一个保证所有矿井电力供应的最小花费。


【输入格式】


第一行一个整数n, 表示矿井总数。 第2~n+1行,每行一个整数, 第i个数v【i】表示在第i口矿井上建立发电站的费用。 接下来为一个nn的矩阵P, 其中p【 i , j 】表示在第i口矿井和第j口矿井之间建立电网的费用(数据保证有p【 i, j 】 = p【 j, i 】, 且 p【 i, i 】=0)。


【输出格式】仅一个整数, 表示//代码效果参考:http://www.lyjsj.net.cn/wx/art_22892.html

让所有矿井获得充足电能的最小花费。

【输入样例】


4


5


4


4


3


0 2 2 2


2 0 3 3


2 3 0 4


2 3 4 0


【输出样例】


9


输出样例说明: 小FF可以选择在4号矿井建立发电站然后把所有矿井都与其建立电网,总花费是 3+2+2+2 =9。


【数据范围】


对于30%的数据: 1<=n<=50;


对于100%的数据: 1<=n<=300; 0<=v【i】, p【i,j】 <=10^5.


分析:


第一眼看上去是一个MST(最小生成树),唯一不同的是题中有一个发电站的概念,如果将它与MST的问题分隔开,先求MST再来选择价值最小的发电站的话(即贪心思路),是不能保证求出最优解的,因为这样就默认了每个矿井都必须是连通的,当边权特别大,不取这条边,分别修两个电站才是最优的。因此贪心的方案是错的,没有把题中两个关键的元素联系起来。正确的解法是在原图的基础上虚拟一个点,原图的每一个节点都与这个虚拟点有一条边,边权为在该点上修建电站的花费。从而得到一个新图,对新图的求MST,结果结果就是MST的边权和。这是一种模型转换的思路,十分值得借鉴。


贪心的思路没有将题目整体考虑,所以要得到正确的解题模型,整体考虑题目往往非常重要。


贪心思路是我在考试时想的错误方法,编程复杂不说还WA了。


下面修改过后用模型转换思路得到的AC代码:


?123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104/ID: ringxu97LANG: C++TASK: NewstartSOLUTION: 生成树/#include#include#include#include#include#include#include#include#includeusing namespace std;const int maxn=300+10;const int inf=0x3f3f3f3f;int n;struct DisjointSet//并查集 { int n; int fa【maxn】; DisjointSet(const int &k):n(k) { for(int i=1;i<=k;++i) fa【i】=i; } int Get(int a) { if(fa【a】==a)return a; else return fa【a】=Get(fa【a】); } void Union(int a,int b) { fa【Get(a)】=Get(b); } bool Same(int a,int b) { return Get(a)==Get(b); }};struct EDGE{ int u,v,w;}E【maxnmaxn/2】;//边表 inline bool cmp(EDGE a,EDGE b){ return a.wu=u; p->v=v; (p++)->w=w;}int price【maxn】;int G【maxn】【maxn】;int ans=0;void read()//读入数据 { scanf("%d",&n); for(int i=1;i<=n;++i) { scanf("%d",price+i); } for(int i=1;i<=n;++i) for(int j=1;j<=n;++j) { int tmp; scanf("%d",&tmp); if(j>i) { addedge(i,j,tmp);//无向边 } } for(int i=1;i<=n;++i) { addedge(i,n+1,price【i】);//虚拟点为n+1,与原图各点连边 }} void Kruskal()//求MST { memset(G,0,sizeof(G)); DisjointSet ds(n+1); sort(E,p,cmp); for(EDGE *i=E;i


u,i->v)) { ans+=i->w; ds.Union(i->u,i->v); } }}int main(){ read(); Kruskal(); printf("%d\n",ans); return 0;}

相关文章
|
算法 Android开发 索引
LeetCode 周赛上分之旅 #44 同余前缀和问题与经典倍增 LCA 算法
学习数据结构与算法的关键在于掌握问题背后的算法思维框架,你的思考越抽象,它能覆盖的问题域就越广,理解难度也更复杂。在这个专栏里,小彭与你分享每场 LeetCode 周赛的解题报告,一起体会上分之旅。
81 0
|
5月前
|
存储 算法 数据挖掘
力扣18题 四数之和:从基础到精通,一篇文章带你突破算法难关
力扣18题 四数之和:从基础到精通,一篇文章带你突破算法难关
|
6月前
|
人工智能
倍增LCA受到启发的一题
倍增LCA受到启发的一题
32 0
|
存储 算法
1【百度之星】基础算法讲解—穷举、贪心(下)
1【百度之星】基础算法讲解—穷举、贪心(下)
|
存储 移动开发 算法
C++/PTA 关于深度优先搜索和逆序对的题应该不会很难吧这件事
背景知识 深度优先搜索与 DFS 序 深度优先搜索算法(DFS)是一种用于遍历或搜索树或图的算法。以下伪代码描述了在树 T 上进行深度优先搜索的过程
116 0
|
机器学习/深度学习 算法
<冲刺大厂之算法刷题>回溯算法(四)
<冲刺大厂之算法刷题>回溯算法
<冲刺大厂之算法刷题>回溯算法(四)
|
存储 算法
<冲刺大厂之算法刷题>回溯算法(一)
<冲刺大厂之算法刷题>回溯算法
<冲刺大厂之算法刷题>回溯算法(一)
|
机器学习/深度学习 C++
【力扣·每日一题】1036. 逃离大迷宫 (C++ bfs 思维)
【力扣·每日一题】1036. 逃离大迷宫 (C++ bfs 思维)
96 0
【力扣·每日一题】1036. 逃离大迷宫 (C++ bfs 思维)
下一篇
无影云桌面