某省调查乡村交通状况,得到的统计表中列出了任意两村庄间的距离。
省政府“畅通工程”的目标是使全省任何两个村庄间都可以实现公路交通(但不一定有直接的公路相连,只要能间接通过公路可达即可),并要求铺设的公路总长度为最小。请计算最小的公路总长度。 

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 - 还是畅通工程的更多相关文章

  1. 【2018寒假集训Day 8】【最小生成树】Prim和Kruskal算法模板

    Luogu最小生成树模板题 Prim 原理与dijkstra几乎相同,每次找最优的点,用这个点去松弛未连接的点,也就是用这个点去与未连接的点连接. #include<cstdio> #in ...

  2. 【数据结构】 最小生成树(二)——kruskal算法

    上一期说完了什么是最小生成树,这一期咱们来介绍求最小生成树的算法:kruskal算法,适用于稀疏图,也就是同样个数的节点,边越少就越快,到了数据结构与算法这个阶段了,做题靠的就是速度快,时间复杂度小. ...

  3. 最小生成树(prim和kruskal)

    最小生成树(prim和kruskal) 最小生成树的最优子结构性质 设一个最小生成树是T.如果选出一个T中的一条边,分裂成的两个树T1,T2依然是它们的点集组成的最小生成树.这可以用反证法来证.反着来 ...

  4. [贪心经典算法]Kruskal算法

    Kruskal算法的高效实现需要一种称作并查集的结构.我们在这里不介绍并查集,只介绍Kruskal算法的基本思想和证明,实现留在以后讨论. Kruskal算法的过程: (1) 将全部边按照权值由小到大 ...

  5. 无向带权图的最小生成树算法——Prim及Kruskal算法思路

    边赋以权值的图称为网或带权图,带权图的生成树也是带权的,生成树T各边的权值总和称为该树的权. 最小生成树(MST):权值最小的生成树. 生成树和最小生成树的应用:要连通n个城市需要n-1条边线路.可以 ...

  6. 最小生成树(Prim算法+Kruskal算法)

    什么是最小生成树(MST)? 给定一个带权的无向连通图,选取一棵生成树(原图的极小连通子图),使生成树上所有边上权的总和为最小,称为该图的最小生成树. 求解最小生成树的算法一般有这两种:Prim算法和 ...

  7. MST最小生成树及克鲁斯卡尔(Kruskal)算法

    最小生成树MST,英文名如何拼写已忘,应该是min spaning tree吧.假设一个无向连通图有n个节点,那么它的生成树就是包括这n个节点的无环连通图,无环即形成树.最小生成树是对边上权重的考虑, ...

  8. [数据结构]最小生成树算法Prim和Kruskal算法

    最小生成树 在含有n个顶点的连通图中选择n-1条边,构成一棵极小连通子图,并使该连通子图中n-1条边上权值之和达到最小,则称其为连通网的最小生成树.  例如,对于如上图G4所示的连通网可以有多棵权值总 ...

  9. 图的最小生成树的理解和实现:Prim和Kruskal算法

    最小生成树 一个连通图的生成树是一个极小的连通子图,它含有图中所有的顶点,但只有足以构成一棵树的n-1条边.我们将构造连通网的最小代价生成树称为最小生成树(Minimum Cost Spanning ...

  10. hdu 1233 还是畅通工程 最小生成树(prim算法 + kruskal算法)

    还是畅通工程                                                                            Time Limit: 4000/2 ...

随机推荐

  1. GitHub客户端和Shell的基本操作和理解

    GitHub客户端和Shell指令的简单实用 客户端操作, web端操作, shell指令操作. 掌握了这三种操作,基本上就可以很好的运用gitHub了. 创建项目, 可以通过web端进行创建. 可以 ...

  2. 修改host文件浏览国外网站

    公司电脑网络没法进github没办法工作需要只能FQ了. 方法1:用VPN 但是地要钱呐,没钱只能放弃了,不过每天试用还是可以的 方法2:改电脑host,文件中每条数据前面的#代表注释.把要访问的地址 ...

  3. Ubuntu下gcc安装

    在Ubuntu下安装GCC和其他一些Linux系统有点不一样. 方法一: 该方法超简单:sudo apt-get  build-depgcc 就上面这条命令就可以搞定 方法二:sudo apt-get ...

  4. 头像文件上传 方法一:from表单 方法二:ajax

    方法一:from表单 html 设置form表单,内包含头像预览div,内包含上传文件input 设置iframe用来调用函数传参路径 <!--表单提交成功后不跳转处理页面,而是将处理数据返回给 ...

  5. hiho1116 - 数据结构 线段树(区间合并)

    题目链接 现在有一个有n个元素的数组a1, a2, ..., an. 记f(i, j) = ai * ai+1 * ... * aj. 初始时,a1 = a2 = ... = an = 0,每次我会修 ...

  6. SGU 180 Inversions【树状数组】

    题意:求逆序数 和POJ那题求逆序数的一样,不过这题离散化之后,要去一下重,然后要开到long long #include<iostream> #include<cstdio> ...

  7. ftp 一个账号多个家目录的解决方案

    通常,配置ftp时,一个ftp账号只对应一个家目录,不能有多个家目录的情况. 但是,根据公司开发项目的需求,需要做到一个ftp对应多个开发目录.有想过创建软链接的,可是发现通过ftp是访问不了的. 举 ...

  8. Reactor Cooling ZOJ - 2314 上下界网络流

    Code: #include<cstdio> #include<algorithm> #include<vector> #include<queue> ...

  9. django 分组统计遇见的问题

    在使用 django 的时候发现了一个坑 例如: In [54]: print(F.objects.all().values("age").annotate(fff=Count(& ...

  10. vue单文件中引用路径的处理

    原文地址:vue单文件中引用路径的处理如有错误,欢迎指正! vue单文件的开发过程中,在单文件模版中可能会涉及到文件路径的处理,比如 <img>, style 中的 background ...