Prim算法很好理解,特别是学完了迪杰斯特拉算法之后,更加能理解Prim的算法思想

和迪杰斯特拉算法差不多,由于最后要形成连通图,故任意指定一个点,作为初始点,遍历所有点,以当前最小权值的点(和迪杰斯特拉不同,每个点的值就由边的权值确定)每次求出其他点的值。

在判断联通图的关系时,并查集是个十分高效的手段,通过并查集能够判断出当前是否成环(在Kruskal算法里用并查集判断是否成环非常重要),还有判断当前是否有路可通

通过HDU 1879来分析Prim算法,以及并查集在MST中的应用

继续畅通工程

Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u

Submit Status

Description

省政府“畅通工程”的目标是使全省任何两个村庄间都可以实现公路交通(但不一定有直接的公路相连,只要能间接通过公路可达即可)。现得到城镇道路统计表,表中列出了任意两城镇间修建道路的费用,以及该道路是否已经修通的状态。现请你编写程序,计算出全省畅通需要的最低成本。
 

Input

测试输入包含若干测试用例。每个测试用例的第1行给出村庄数目N ( 1< N < 100 );随后的 N(N-1)/2 行对应村庄间道路的成本及修建状态,每行给4个正整数,分别是两个村庄的编号(从1编号到N),此两村庄间道路的成本,以及修建状态:1表示已建,0表示未建。

当N为0时输入结束。

 

Output

每个测试用例的输出占一行,输出全省畅通需要的最低成本。
 

Sample Input

3
1 2 1 0
1 3 2 0
2 3 4 0
3
1 2 1 0
1 3 2 0
2 3 4 1
3
1 2 1 0
1 3 2 1
2 3 4 1
0
 

Sample Output

3
1
0
 
 
#include <iostream>
#include <cstdio>
#include <cstring>
#define inf 10000000
using namespace std;
int towns[][]; //用邻接矩阵存贮图中边的权值
int lowcost[]; //存贮点的值
bool vis[];
int father[];
int findset(int x) //经典的并查集 路径压缩查找root节点,接下来要用到它
{
if (x!=father[x])
father[x]=findset(father[x]);
return father[x];
}
int main()
{
int n,m;
while (scanf("%d",&n)&&n)
{
int i,j,k;
m=n*(n-)/;
for (i=; i<=n; i++) //初始化部分,我一般首先将边和点的值全部初始化为inf
{
for (j=;j<=n;j++)
towns[i][j]=inf;
father[i]=i;
lowcost[i]=inf;
} for (j=;j<=m;j++) //读入边的权值
{
int a,b,c,d;
scanf("%d %d %d %d",&a,&b,&c,&d);
if (d==) //根据题目要求,d为1的时候代表路已经修通,故用并查集把所有修通了路的节点汇集在一个集合中
{
int root=findset(a);
int r2=findset(b);
father[r2]=root;
}
else
if (towns[a][b]>c) //有些题目会比较坑,两点之间有多条路,而且题目里面还没有任何提示,所以加上这句判断较为保险
towns[a][b]=towns[b][a]=c; //无向图,双向都要设置权值
}
lowcost[]=; //我一般设置从1点出发进行连通,故将点1的权值设置为0
memset(vis,,sizeof vis);
int ans=;
for (i=; i<=n; i++) //prim核心部分。
{
int min=inf,loc=;
for (j=;j<=n;j++) //先找出lowcost最小的点,即点权值最小的点
{
if (vis[j]||lowcost[j]==inf) continue;
if (min>lowcost[j]) min=lowcost[j],loc=j;
} vis[loc]=; //通过vis数组将已经连通且权值最小的点 设置为已访问状态。 ans+=lowcost[loc]; //prim里面点的权值和Dijstla不同,这里保存的就是连通边的权值。所以求结果的时候是累加点权值即可
for (k=;k<=n;k++)
{
if (findset(k)==findset(loc)) towns[loc][k]=;//并查集派上用场了,一旦并查为同一集合,说明路已经修好,边权值设置为0
if (k==loc||vis[k]) continue;
if (lowcost[k]>towns[loc][k]) //由当前点向其他未连通点 进行 “尝试连通”
lowcost[k]=towns[loc][k]; }
}
printf("%d\n",ans);
}
return ;
}

MST(最小生成树)——Prim算法——HDU 1879-继续畅通工程的更多相关文章

  1. hdu 1879 继续畅通工程

    /************************************************************************/ /* hdu 1879 继续畅通工程 Time L ...

  2. hdu 1879 继续畅通工程 (并查集+最小生成树)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1879 继续畅通工程 Time Limit: 2000/1000 MS (Java/Others)    ...

  3. HDU 1879 继续畅通工程 (Prim(普里姆算法)+Kruskal(克鲁斯卡尔))

    继续畅通工程 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Sub ...

  4. hdu 1879 继续畅通工程 (最小生成树)

    继续畅通工程 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Subm ...

  5. HDU 1879 继续畅通工程(最小生成树)

    省政府“畅通工程”的目标是使全省任何两个村庄间都可以实现公路交通(但不一定有直接的公路相连,只要能间接通过公路可达即可).现得到城镇道路统计表,表中列出了任意两城镇间修建道路的费用,以及该道路是否已经 ...

  6. HDU 1879 继续畅通工程(Kruskra)

    继续畅通工程 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Sub ...

  7. hdu 1879 继续畅通工程(最小生成树,基础)

    题目 #define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<string.h> #include<algo ...

  8. HDU 1879 继续畅通工程(Prim||Kruscal模板题)

    原题链接 Prim(点归并) //异或运算:相同为假,不同为真 #include<cstdio> #include<algorithm> #define maxn 105 us ...

  9. (step6.1.1)hdu 1879(继续畅通工程——最小生成树、kruscal)

    题目大意:输入一个整数n,表示有n个村庄.在接下来的n(n-1)/2行中,每行有4个整数begin  end  weight  flag.分别表示从begin到end之间可以连通 ,他们之间的费用为w ...

随机推荐

  1. 嵊州普及Day2T2

    题意:对于n个数的数列,进行排列,求第m个大于此数列的数列. 思路:查找后2个是否逆序,若是,将后3个递归.如此运算,找后面大于此数中最小数交换,然后将后面数列顺序排列. 相对简单. 见代码: #in ...

  2. maven package跳过测试

    mvn clean package -DskipTests 或者 mvn clean package -Dmaven.test.skip=true 区别 -DskipTests,不执行测试用例,但编译 ...

  3. 《ES6标准入门》(阮一峰)--8.函数的扩展

    1.函数参数的默认值 基本用法 ES6 之前,不能直接为函数的参数指定默认值,只能采用变通的方法. function log(x, y) { y = y || 'World'; console.log ...

  4. HDU - 1394 Minimum Inversion Number(线段树求逆序数---点修改)

    题意:给定一个序列,求分别将前m个数移到序列最后所得到的序列中,最小的逆序数. 分析:m范围为1~n,可得n个序列,求n个序列中最小的逆序数. 1.将序列从头到尾扫一遍,用query求每个数字之前有多 ...

  5. JS - 查找字符串中的某个值,截取其之前。和之后的值

    var str = "11:222"; /* *   截取 “ :”之前和之后的值 */document.write(str.split(':')[0])    //输出11doc ...

  6. 文本编辑器vim/vi——末行模式

    指令格式: #vim 文件路径作用:打开指定的文件. 进入方式:由命令模式进入,按下“:”或者“/(表示查找)”即可进入 退出方式: a. 按下esc b. 连按2次esc键 c. 删除末行全部输入字 ...

  7. Arduino函数

    输入输出函数 pinMode(pin, mode)将数位脚位(digital pin)指定为输入或输出.如:pinMode(7,INPUT); // 将脚位 7 设定为输入模式 digitalWrit ...

  8. python爬取网页文本、图片

    从网页爬取文本信息: eg:从http://computer.swu.edu.cn/s/computer/kxyj2xsky/中爬取讲座信息(讲座时间和讲座名称) 注:如果要爬取的内容是多页的话,网址 ...

  9. Mac使用安卓模拟器-网易MuMu

    先看下效果图 近期,因为小编把安卓手机倒手了,但现在还想看看一些安卓应用.所以就搜罗了很多市场上的模拟器. 最终选定了网易的MuMu,总体感觉网易也是花了很大的心思,整体效果超赞. 下载地址 网易Mu ...

  10. Linux基础学习准备

    Linux 基础学习准备 工欲善其事必先利其器,还是买个服务器折腾比较好. 虚拟机和镜像 推荐吾爱的:吾爱虚拟机2.0 CentOS镜像: Centos国内下载源 http://man.linuxde ...