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

解题思路:①Prim算法的核心就是加点法,每次把离目标集合最小权值的一点加入其中。其算法跟Dijkstra大同小异,不同的是mincost数组记录的是当前点到目标集合的最小权值,下次就取最小权值的端点加入就可以了。其算法时间复杂度是O(n2),适合于稠密图。
②Kruskal算法的核心就是加边法,并且运用到并查集。先将各边权值按升序排列,然后贪心加边,加边时查看当前边的两端点是否为同一个连通图中的两点,如果是的话,就不能纳入目标集合,因为会出现回路,即产生圈,这样就不满足树的定义了,否则将其加入。其原来的时间复杂度是O(n2),使用并查集之后时间复杂度是O(elogn),适合于稀疏图。
AC代码之Prim算法:
 #include<bits/stdc++.h>
using namespace std;
const int INF = 0x3f3f3f3f;
const int maxn = ;
int n,a,b,c,mincost[maxn],cost[maxn][maxn];
bool vis[maxn];
int Prim(){//加点法
for(int i=;i<=n;++i)//这里选取节点1作为起点,mincost为各节点到最小生成树节点集合的最小权值
mincost[i]=cost[][i];
mincost[]=;vis[]=true;//标记已访问
int res=;//计算最小生成树的权值
for(int i=;i<n;++i){
int k=-;//标记为-1
for(int j=;j<=n;++j)//找出到最小生成树节点集合的权值最小的还没入集合的一点
if(!vis[j] && (k==- || mincost[k]>mincost[j]))k=j;
if(k==-)break;//如果还是-1,表示已经完成最小生成树的建立
vis[k]=true;//将节点k纳入最小生成树节点的集合
res+=mincost[k];//加上其权值
for(int j=;j<=n;++j)//更新k的邻接点到最小生成树节点集合的最小权值
if(!vis[j])mincost[j]=min(mincost[j],cost[k][j]);//还没归纳的节点
}
return res;
}
int main()
{
while(~scanf("%d",&n) && n){
memset(vis,false,sizeof(vis));
for(int i=;i<=n;++i){
for(int j=;j<=n;++j)
cost[i][j]=(i==j?:INF);
}
for(int i=;i<=n*(n-)/;++i){
cin>>a>>b>>c;
cost[a][b]=cost[b][a]=c;
}
printf("%d\n",Prim());
}
return ;
}

AC代码之Kruskal算法:

 #include<bits/stdc++.h>
using namespace std;
int n,father[],height[];
struct edge{int u,v,cost;}es[];
bool cmp(const edge& e1,const edge& e2){
return e1.cost<e2.cost;
}
void init_union_find(){//将每个节点当作根节点
for(int i=;i<=n;++i)father[i]=i;
}
int find_father(int x){//递归查找根节点
if(father[x]==x)return x;
else return father[x]=find_father(father[x]);
}
bool same_father(int x,int y){//查找两点的根节点是否相同
return find_father(x)==find_father(y);
}
void unite(int x,int y){
x=find_father(x);
y=find_father(y);
if(x==y)return;//如果为同一个连通图,直接返回
if(height[x]<height[y])father[x]=y;//高度大的当作高度小的父亲
else{
father[y]=x;
if(height[x]==height[y])height[x]++;//如果合并前两棵树的高度相等,加入一节点后树的高度就加1
}
}
int Kruskal(){
sort(es+,es+n*(n-)/+,cmp);//权值按从小到大排序
init_union_find();//并查集的初始化
int res=;
for(int i=;i<=n*(n-)/;++i){
edge e=es[i];
if(!same_father(e.u,e.v)){//如果两点的根节点不同,即为非连通图
unite(e.u,e.v);//归并到同一个集合
res+=e.cost;//加入权值
}
}
return res;
}
int main()
{
while(~scanf("%d",&n) && n){
for(int i=;i<=n*(n-)/;++i)
scanf("%d %d %d",&es[i].u,&es[i].v,&es[i].cost);
memset(height,,sizeof(height));//初始化树的高度为0
printf("%d\n",Kruskal());
}
return ;
}

克鲁斯卡尔简化版代码:

 #include<bits/stdc++.h>
using namespace std;
int n,father[],sum;
struct edge{int u,v,cost;}es[];
bool cmp(const edge& e1,const edge& e2){
return e1.cost<e2.cost;
}
void init_union_find(){//将每个节点当作根节点
for(int i=;i<=n;++i)father[i]=i;
}
int find_father(int x){//递归查找根节点
if(father[x]==x)return x;
else return father[x]=find_father(father[x]);
}
void unite(int x,int y,int z){
x=find_father(x);
y=find_father(y);
if(x!=y){//如果边的两端点的根节点不相同,即分别为非连通图,则可以归并
sum+=z;//加上最小权值
father[x]=y;//将x的父节点改成y,也就是现在x的根节点是y的根节点,注意这里只是简单的修改,和上面归纳到同一个集合不太一样
}
}
int main()
{
while(~scanf("%d",&n) && n){
for(int i=;i<=n*(n-)/;++i)
scanf("%d %d %d",&es[i].u,&es[i].v,&es[i].cost);
sort(es+,es+n*(n-)/+,cmp);//权值按从小到大排序
sum=;init_union_find();//初始化
for(int i=;i<=n*(n-)/;++i)
unite(es[i].u,es[i].v,es[i].cost);
printf("%d\n",sum);
}
return ;
}

题解报告:hdu 1233 还是畅通工程的更多相关文章

  1. HDU.1233 还是畅通工程(Prim)

    HDU.1233 还是畅通工程(Prim) 题意分析 首先给出n,代表村庄的个数 然后出n*(n-1)/2个信息,每个信息包括村庄的起点,终点,距离, 要求求出最小生成树的权值之和. 注意村庄的编号从 ...

  2. HDU 1233 还是畅通工程(Kruskal算法)

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1233 还是畅通工程 Time Limit: 4000/2000 MS (Java/Others)   ...

  3. hdu 1233 还是畅通工程 (最小生成树)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1233 还是畅通工程 Time Limit: 4000/2000 MS (Java/Others)    ...

  4. hdu 1233 - 还是畅通工程(MST)

    还是畅通工程 Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Subm ...

  5. HDU 1233 还是畅通工程 (最小生成树 )

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

  6. HDU 1233 还是畅通工程(最小生成树)

    传送门 还是畅通工程 Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total ...

  7. HDU 1233 还是畅通工程 (最小生成树)

    还是畅通工程 Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Subm ...

  8. hdu 1233 还是畅通工程 并查集or最小生成树

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

  9. hdu 1233:还是畅通工程(数据结构,图,最小生成树,普里姆(Prim)算法)

    还是畅通工程 Time Limit : 4000/2000ms (Java/Other)   Memory Limit : 65536/32768K (Java/Other) Total Submis ...

随机推荐

  1. python3支持excel读写

    1.安装setuptools-17.0.tar.gz cmd 进入命令行 cd C:\Users\vivi\Desktop\pythonforexcel\setuptools-17.0\setupto ...

  2. [bzoj1004][HNOI2008][Cards] (置换群+Burnside引理+动态规划)

    Description 小春现在很清闲,面对书桌上的N张牌,他决定给每张染色,目前小春只有3种颜色:红色,蓝色,绿色.他询问Sun有多少种染色方案,Sun很快就给出了答案.进一步,小春要求染出Sr张红 ...

  3. java Beanutils.copyProperties( )用法

    这是一篇开发自辩甩锅稿~~~~ 昨天测试小姐姐将我的一个bug单重开了,emmmm....内心OS:就调整下对象某个属性类型这么简单的操作,我怎么可能会出错呢,一定不是我的锅!!but再怎么抗拒,bu ...

  4. java 访问对象私有变量

    Captcha captcha = getCaptcha(captchaId); // 通过反射获取验证码值 Class<?> classType = captcha.getClass() ...

  5. 【UOJ34】高精度乘法(FFT)

    题意: 思路:FFT模板,自带10倍常数 type cp=record x,y:double; end; arr=..]of cp; var a,b,cur:arr; n,m,n1,n2,i,j:lo ...

  6. new出来的对象无法调用@Autowired注入的Spring Bean

    @Autowired注入Spring Bean,则当前类必须也是Spring Bean才能调用它,不能用new xxx()来获得对象,这种方式获得的对象无法调用@Autowired注入的Bean. 1 ...

  7. Android: 清除View跳转的历史记录

    Intent intent = new Intent(); intent.setClass(SetActivity.this, RegisterLoginActivity.class); intent ...

  8. Pixhawk---超声波模块加入说明(I2C方式)

    1 说明   在Pixhawk的固件中,已经实现了串口和i2c的底层驱动,并不须要自己去写驱动.通过串口的方式加入超声波的缺点是串口不够.不能加入多个超声波模块,此时须要用到i2c的方式去加入了.在P ...

  9. 改动grub默认启动顺序

    grub如今有两个版本号,一个grub,一个grub2,两个版本号的操作不太一样. 装centos的朋友非常有可能是grub.我电脑装的是ubuntu14.04,为grub2.我演示grub2的过程. ...

  10. Matlab得到二值图像中最大连通区域

    有时候要将二值化图像中最大的连通域保存下来.以下函数提供了一种方法: %function [img]=maxLianTongYu(I):求图像中最大的连通域 %输入:I 输入图像 %输出:img 仅包 ...