最小生成树(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 ...
随机推荐
- FastJSON杂项
//通过TypeReference解决泛型的问题 List<Integer> rst = JSON.parseObject(v,new TypeReference<List<I ...
- Mysql语法:navicat for mysql 添加注释
在 navicat 中有三种注释的书写方式: 以 # 开头的字符串,可以多个 # 连续以 – 开头的字符串,注意:只能是 – ,而且 – 后面需要加一个半角空格以 /* */ 包围的字符串,类似于 J ...
- POJ 2976 Dropping tests【二分 最大化平均值】
题意:定义最大平均分为 (a1+a2+a3+---+an)/(b1+b2+---+bn),求任意去除k场考试的最大平均成绩 和挑战程序设计上面的最大化平均值的例子一样 判断是否存在x满足条件 (a1+ ...
- shell简单监控脚本模板
#!/bin/bash host=127.0.0.1user=adminpassword='xx'port=6032x=0check_proxy(){v=$(mysql -N -u$user -p$p ...
- Concurrency pattern
In software engineering, concurrency patterns are those types of design patterns that deal with the ...
- 前端换行显示,后端返回<br>
- [agc016d]xor replace
题意: 题解: 棒棒的神仙题...这题只是D题???(myh:看题五分钟,讨论两小时) 首先这个异或和是假的,比如我现在有$a=(a_1,a_2,a_3,a_4)$,操作一下$a_2$,就变成了$a= ...
- 异步调用task
异步主要用来提升程序性能,会增加系统的开销(新建一个线程去执行异步任务). 可应用于耗时长的操作,比如:访问数据库时(应用程序和数据库不在同一台服务器上).服务之间的调用(服务会分散在不同的服务器上) ...
- BZOJ 2794 [Poi2012]Cloakroom(离线+背包)
2794: [Poi2012]Cloakroom Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 406 Solved: 241[Submit][St ...
- 洛谷P2870 [USACO07DEC]最佳牛线,黄金Best Cow Line, Gold
思路大概和其他的题解一样: 从当前字符串最前面,最后面选一个字典序较小的然后拉到一个新的字符串序列中,如果相同就一直往中间扫描直到发现不同为止(一个字符如果被选中之后那么就不可以再次选择了),所以我们 ...