【基础练习】【并查集】codevs2796 最小完全图题解
2015-11-03 15:25
344 查看
题目描述 Description
若一个图的每一对不同顶点都恰有一条边相连,则称为完全图。
最小生成树MST在Smart的指引下找到了你,希望你能帮它变成一个最小完全图(边权之和最小的完全图)。
注意:必须保证这个最小生成树MST对于最后求出的最小完全图是唯一的。
输入描述 Input Description
第一行一个整数n,表示生成树的节点数。
接下来有n-1行,每行有三个正整数,依次表示每条边的顶点编号和边权。
(顶点的边号在1-n之间,边权<231)
输出描述 Output Description
一个整数ans,表示以该树为最小生成树的最小完全图的边权之和。
样例输入 Sample Input
4
1 2 1
1 3 1
1 4 2
样例输出 Sample Output
12
数据范围及提示 Data Size & Hint
30%的数据:n<1000;
100%的数据:n≤20000,所有的边权<231。
用克鲁斯卡尔做,读入边然后跑最小生成树,只不过不检查每条边的端点是否属于两个集合(因为本来读入的就是最小生成树,当然在两个集合) 而是统计当前两个集合的元素数size 然后每次加边时 ans+=(sz[x]*sz[y]-1)*(e[i].w+1);即可,因为此时左右两个集合都是完全图 但两个集合互不连通 要想让他们完全联通且保证加入的边严格最小 就要让两边集合元素两两连一条边(当前边除外) 权值为当前最小边权+1
应该很好理解
下面讲一下部分分怎么拿 这里以codevs这道题的数据为标准(我们校内胡测数据更强= =)
LCA做法:画图不难发现,对于每两个点,如果要在他们中间连一条边且不能属于最小生成树,那么这条边权最少要是这两个点从最小生成树上连通经过的最长的边+1
那么好办了,我们做一个LCA即可 每次查找两点之间的最长边 ans+=最长边权+1
这个算法的致命缺陷是,由于数据规模大,而LCA需要枚举所有点对,所以会T
codevs过6个点 我们自己的数据只过了3个点
实际上分析可以发现,LCA做法重复计算了很多状态 比如如果E是D的儿子且和A分属两个子树 那么我们从D与A的值即可推E 却重复计算了很多状态
其实仔细想想 这题如果空间开大些 还可以用DP
BFS/DFS做法 不说了 枚举找即可= = codevs20分 我们的数据全T
那么正解代码
——初闻征雁已无蝉,百尺楼高水接天
若一个图的每一对不同顶点都恰有一条边相连,则称为完全图。
最小生成树MST在Smart的指引下找到了你,希望你能帮它变成一个最小完全图(边权之和最小的完全图)。
注意:必须保证这个最小生成树MST对于最后求出的最小完全图是唯一的。
输入描述 Input Description
第一行一个整数n,表示生成树的节点数。
接下来有n-1行,每行有三个正整数,依次表示每条边的顶点编号和边权。
(顶点的边号在1-n之间,边权<231)
输出描述 Output Description
一个整数ans,表示以该树为最小生成树的最小完全图的边权之和。
样例输入 Sample Input
4
1 2 1
1 3 1
1 4 2
样例输出 Sample Output
12
数据范围及提示 Data Size & Hint
30%的数据:n<1000;
100%的数据:n≤20000,所有的边权<231。
用克鲁斯卡尔做,读入边然后跑最小生成树,只不过不检查每条边的端点是否属于两个集合(因为本来读入的就是最小生成树,当然在两个集合) 而是统计当前两个集合的元素数size 然后每次加边时 ans+=(sz[x]*sz[y]-1)*(e[i].w+1);即可,因为此时左右两个集合都是完全图 但两个集合互不连通 要想让他们完全联通且保证加入的边严格最小 就要让两边集合元素两两连一条边(当前边除外) 权值为当前最小边权+1
应该很好理解
下面讲一下部分分怎么拿 这里以codevs这道题的数据为标准(我们校内胡测数据更强= =)
LCA做法:画图不难发现,对于每两个点,如果要在他们中间连一条边且不能属于最小生成树,那么这条边权最少要是这两个点从最小生成树上连通经过的最长的边+1
那么好办了,我们做一个LCA即可 每次查找两点之间的最长边 ans+=最长边权+1
这个算法的致命缺陷是,由于数据规模大,而LCA需要枚举所有点对,所以会T
codevs过6个点 我们自己的数据只过了3个点
实际上分析可以发现,LCA做法重复计算了很多状态 比如如果E是D的儿子且和A分属两个子树 那么我们从D与A的值即可推E 却重复计算了很多状态
其实仔细想想 这题如果空间开大些 还可以用DP
BFS/DFS做法 不说了 枚举找即可= = codevs20分 我们的数据全T
那么正解代码
//copyright by ametake #include #include #include #include #include #include typedef long long ll; using namespace std; const ll maxn=100000+10; struct node { ll u,v,w; bool operator < (node nb) const { return w
——初闻征雁已无蝉,百尺楼高水接天
相关文章推荐
- 详解图的应用(最小生成树、拓扑排序、关键路径、最短路径)
- 最小生成树算法之Prim算法
- 使用C语言实现最小生成树求解的简单方法
- 最小生成树算法——Prim和Kruskal算法的实现
- Data Structure - Week 15
- HDU-1213-How Many Tables
- Longest Consecutive Sequence,Distinct Subsequences,Interleaving String,Scramble String
- poj 2485 Highways
- HDU1301 最小生成树kruskal裸题
- SARS病毒传染 并查集
- Kruskal 最小生成树
- 最小生成树
- HDU 1213
- CSU1307 并查集+SPFA
- 图的最小生成树学习笔记
- BestWiring——Kruskal算法&并查集
- 朋友圈(使用并查集)的实现
- 并查集的应用
- 图—并查集(解决朋友圈问题)
- 并查集