最小生成树(MST) prim() 算法 kruskal()算法 A - 还是畅通工程
Input
测试输入包含若干测试用例。
每个测试用例的第1行给出村庄数目N ( < 100 );随后的N(N-1)/2行对应村庄间的距离,每行给出一对正整数,分别是两个村庄的编号,以及此两村庄间的距离。为简单起见,村庄从1到N编号。
当N为0时,输入结束,该用例不被处理。
Output
对每个测试用例,在1行里输出最小的公路总长度。
Sample Input
3
1 2 1
1 3 2
2 3 4
4
1 2 1
1 3 4
1 4 1
2 3 3
2 4 2
3 4 5
0
Sample Output
3
5 Huge input, scanf is recommended. 下面有一些我写代码时使用到的代码变量:
邻接矩阵(Adjacency Matrix)
无穷大(infinite)
顶点(vertex)
权值(cost)
初始化(initialize)
临时工(temp)
整型最大数值=0x7fffffff
AC代码:
1.prim算法
#include<iostream>
#include<stdio.h>
#define N 110
#define inf 0x7fffffff
int cost[N][N];
int ver[N];
int n,a,b,l,temp,v,k=;
using namespace std;
int initia(){//顶点及储存权值的邻接矩阵的初始化
for(int i=;i<=n;i++)
for(int j=;j<=n;j++){
if(i==j) cost[i][j]=;
else cost[i][j]=inf;
ver[i]=;
}
ver[]=;
return ;
}
int prim(){
int sumcost=,mincost;
int temp,v;
for(int vsum=1;vsum<n;vsum++)//顶点总数的记录,当所有顶点都被选中时跳出循环
{
mincost=inf;//一个标志用于筛选最小权值的判断条件
for(v=1;v<=n;v++)
{
if(ver[v]==)//所有可选顶点起点的筛选
{
for(int j=1;j<=n;j++)//遍历所有顶点
{
if(cost[v][j]!=&&cost[v][j]<mincost&&ver[j]!=1)//除去自身及不可达的顶点
{
mincost=cost[v][j];//选出最小权值
temp=j;//记录节点
}
}
}
}
ver[temp]=;//顶点标为已经被选中
cost[v][temp]=cost[temp][v]=0;//边标志为已经被选中
sumcost+=mincost;//记录所有路径权值总和
}
cout<<sumcost<<endl;
return ;
}
int main()
{
while(cin>>n&&n!=){
initia();
int t=n*(n-)/;
while(t--){
cin>>a>>b>>l;
cost[a][b]=cost[b][a]=l;
}
prim();
}
return ;
}
用于记录的数组的下标是从1开始的,且注意红色标记地方,vsum的循环次数不要增加,否则会出错!
这里还有一份其他人的代码,红色部分大大减少了运行时的重复次数,没太看懂!
#include<stdio.h>
#include<iostream>
#define INF 99999999
#define N 110
using namespace std;
int n,G[N][N];
void prim()
{
int p[N],vis[N],i,j,v,sum,m,last,k =;
p[k++] = 1;
sum = ;
for(i=;i<=n;i++) vis[i]=;
vis[] = ;
for(m=;m<n;m++)
{
int min = INF;
for(j=0;j<k;j++)
{
v = p[j];
for(i=;i<=n;i++)
{
if(!vis[i]&& G[v][i]<min){
min = G[v][i];
cout<<"cost v"<<v<<" i"<<i<<":"<<G[v][i]<<endl;
last = i;
}
}
}
vis[last] = ;
p[k++] = last;
sum += min;
}
printf("%d\n",sum);
}
int main()
{
int t,m,i,j,a,b,c;
while(scanf("%d",&n),n)
{
for(i=;i<=n;i++){
for(j=;j<=n;j++)
G[i][j] = INF;
}
m = n*(n-)/;
while(m--){
scanf("%d%d%d",&a,&b,&c);
if( c<G[a][b] || c<G[b][a] )//去重边
G[a][b] = G[b][a] = c;
}
prim();
}
return ;
}
2.kruskal算法
这个代码还没有过,我还在找原因
先存着
#include<iostream>
#include<stdio.h>
#define N 110
#define inf 0x7fffffff
int cost[N][N];
int ver[N];
int n,a,b,l,tempi,tempj;
using namespace std;
int initia(){//顶点及储存权值的邻接矩阵的初始化
for(int i=;i<=n;i++)
for(int j=;j<=n;j++){
if(i==j) cost[i][j]=;
else cost[i][j]=inf;
ver[i]=;
}
return ;
}
int judge(int i,int j){
if(ver[i]==&&ver[j]==) return ;
else return ;
}
int kruskal()
{
int sumcost=,mincost;
for(int esum=;esum<n-;esum++)//边总数的记录,当边的总数为n-1时跳出循环
{
mincost=inf;
for(int i=;i<=n;i++)
for(int j=;j<=n;j++)
if(cost[i][j]!=&&cost[j][i]!=&&cost[i][j]<mincost&&cost[j][i]<mincost&&judge(i,j))//除去自身及不可达的顶点
{
mincost=cost[i][j];//选出最小权值
tempi=i;//记录节点
tempj=j;//记录节点
}
ver[tempi]=;//顶点标为已经被选中
ver[tempj]=;//顶点标为已经被选中
cost[tempi][tempj]=cost[tempj][tempi]=;//边标志为已经被选中
sumcost+=mincost;//记录所有路径权值总和
}
cout<<sumcost<<endl;
return ;
}
int main()
{
while(cin>>n&&n!=){
initia();
int t=n*(n-)/;
while(t--){
cin>>a>>b>>l;
cost[a][b]=cost[b][a]=l;
}
kruskal();
}
return ;
}
最小生成树(MST) prim() 算法 kruskal()算法 A - 还是畅通工程的更多相关文章
- 【2018寒假集训Day 8】【最小生成树】Prim和Kruskal算法模板
Luogu最小生成树模板题 Prim 原理与dijkstra几乎相同,每次找最优的点,用这个点去松弛未连接的点,也就是用这个点去与未连接的点连接. #include<cstdio> #in ...
- 【数据结构】 最小生成树(二)——kruskal算法
上一期说完了什么是最小生成树,这一期咱们来介绍求最小生成树的算法:kruskal算法,适用于稀疏图,也就是同样个数的节点,边越少就越快,到了数据结构与算法这个阶段了,做题靠的就是速度快,时间复杂度小. ...
- 最小生成树(prim和kruskal)
最小生成树(prim和kruskal) 最小生成树的最优子结构性质 设一个最小生成树是T.如果选出一个T中的一条边,分裂成的两个树T1,T2依然是它们的点集组成的最小生成树.这可以用反证法来证.反着来 ...
- [贪心经典算法]Kruskal算法
Kruskal算法的高效实现需要一种称作并查集的结构.我们在这里不介绍并查集,只介绍Kruskal算法的基本思想和证明,实现留在以后讨论. Kruskal算法的过程: (1) 将全部边按照权值由小到大 ...
- 无向带权图的最小生成树算法——Prim及Kruskal算法思路
边赋以权值的图称为网或带权图,带权图的生成树也是带权的,生成树T各边的权值总和称为该树的权. 最小生成树(MST):权值最小的生成树. 生成树和最小生成树的应用:要连通n个城市需要n-1条边线路.可以 ...
- 最小生成树(Prim算法+Kruskal算法)
什么是最小生成树(MST)? 给定一个带权的无向连通图,选取一棵生成树(原图的极小连通子图),使生成树上所有边上权的总和为最小,称为该图的最小生成树. 求解最小生成树的算法一般有这两种:Prim算法和 ...
- MST最小生成树及克鲁斯卡尔(Kruskal)算法
最小生成树MST,英文名如何拼写已忘,应该是min spaning tree吧.假设一个无向连通图有n个节点,那么它的生成树就是包括这n个节点的无环连通图,无环即形成树.最小生成树是对边上权重的考虑, ...
- [数据结构]最小生成树算法Prim和Kruskal算法
最小生成树 在含有n个顶点的连通图中选择n-1条边,构成一棵极小连通子图,并使该连通子图中n-1条边上权值之和达到最小,则称其为连通网的最小生成树. 例如,对于如上图G4所示的连通网可以有多棵权值总 ...
- 图的最小生成树的理解和实现:Prim和Kruskal算法
最小生成树 一个连通图的生成树是一个极小的连通子图,它含有图中所有的顶点,但只有足以构成一棵树的n-1条边.我们将构造连通网的最小代价生成树称为最小生成树(Minimum Cost Spanning ...
- hdu 1233 还是畅通工程 最小生成树(prim算法 + kruskal算法)
还是畅通工程 Time Limit: 4000/2 ...
随机推荐
- nyoj--84--阶乘的0(数学技巧)
阶乘的0 时间限制:3000 ms | 内存限制:65535 KB 难度:3 描述 计算n!的十进制表示最后有多少个0 输入 第一行输入一个整数N表示测试数据的组数(1<=N<=100 ...
- inkscape
最近的论文需要把latex公式放到图里,于是想起了装了之后一直没怎么用的inkscape.因为visio貌似没法直接贴latex格式的公式. 找了几个用法: http://blog.sciencene ...
- (转载)Mac下使用Android Studio 获取 SHA1和MD5
Mac下使用Android Studio 获取 SHA1和MD5 2015-08-10 15:38 1776人阅读 评论(1) 收藏 举报 分类: Android(14) 版权声明:本文为博主原创 ...
- jQuery学习(七)——使用JQ完成下拉列表左右选择
1.需求:实现以下功能 2.步骤分析: 第一步:确定事件(鼠标单击事件click) 第二步:获取左侧下拉列表被选中的option($(“#left option:selected”)) [假设左侧se ...
- shell脚本执行的三种方式
(1) bash script_name 或 sh script_name 推荐使用此方法,script_name 不需要执行权限亦可执行. (2) path/script_name 或 ...
- 【BZOJ2006】【NOI2010】超级钢琴
题意: Description 小Z是一个小有名气的钢琴家,最近C博士送给了小Z一架超级钢琴,小Z希望能够用这架钢琴创作出世界上最美妙的音乐. 这架超级钢琴可以弹奏出n个音符,编号为1至n.第i个音符 ...
- POJ 1198 / HDU 1401 Solitaire (记忆化搜索+meet in middle)
题目大意:给你一个8*8的棋盘,上面有四个棋子,给你一个初始排布,一个目标排布,每次移动,可以把一个棋子移动到一个相邻的空位,或者跨过1个相邻的棋子,在保证棋子移动不超过8次的情况下,问能否把棋盘上的 ...
- 超简单入门Vuex小示例
写在前面 本文旨在通过一个简单的例子,练习vuex的几个常用方法,使初学者以最快的速度跑起来一个vue + vuex的示例. 学习vuex需要你知道vue的一些基础知识和用法.相信点开本文的同学都具备 ...
- vue中的methods、computed和watch
1.computed属性: 经过处理返回的数据值,只要源数据没有发生改变,computed函数里面对相应的数据就不会反生改变,相当于缓存在本地;发生改变的时候,computed对应数据的函数才会发生改 ...
- 【BZOJ 1207】[HNOI2004]打鼹鼠
[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 时间是按顺序的. 所以就有单调性啦. 写个DP就好. 设f[i]表示打第i只鼹鼠,最多能打几只鼹鼠. 则如果i和j的距离不超过它们的 ...