POJ 2421 Constructing Roads (Kruskal算法+压缩路径并查集 )
| Time Limit: 2000MS | Memory Limit: 65536K | |
| Total Submissions: 19884 | Accepted: 8315 |
Description
We know that there are already some roads between some villages and
your job is the build some roads such that all the villages are connect
and the length of all the roads built is minimum.
Input
first line is an integer N (3 <= N <= 100), which is the number
of villages. Then come N lines, the i-th of which contains N integers,
and the j-th of these N integers is the distance (the distance should be
an integer within [1, 1000]) between village i and village j.
Then there is an integer Q (0 <= Q <= N * (N + 1) / 2). Then
come Q lines, each line contains two integers a and b (1 <= a < b
<= N), which means the road between village a and village b has been
built.
Output
should output a line contains an integer, which is the length of all the
roads to be built such that all the villages are connected, and this
value is minimum.
Sample Input
3
0 990 692
990 0 179
692 179 0
1
1 2
Sample Output
179
题目分析:
输入n个村庄,再输入一个邻接矩阵表示点到点的距离,再输入m条边,表示这m条边已经连接,不用考虑路径长度了,求如果想把所有的点都连接
还需要最短再修多长?
算法分析:此题目和标准的模板有所差别,题目输入是一个二维邻接矩阵的值,然后在输入m条已经联通的边,也就是说这些边已经连接好了,这些
边长就不要计算了。用Kruskal算法,并查集不仅要初始化,还要对这些边进行关联处理,建立父子关系。
代码:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <algorithm> using namespace std; struct node
{
int u;
int v;
int w;
bool operator <(const node&x)const //node类自己的运算符重载,这样在sort时,直接写就可以了,不用调用函数了
{
return w<x.w;
}
}q[5000]; int fa[105];
int findset(int x)
{
return fa[x]!=x?fa[x]=findset(fa[x]):x;
} //带压缩路径的并查集 int main()
{
int n, m;
int u, v;
int i, j;
int dd;
int e=0;
scanf("%d", &n);
for(i=1; i<=n; i++)
{
for(j=1; j<=n; j++)
{
scanf("%d", &dd ); //因为是无向图,所以只需要存储一个上三角的数据或者下三角的数据就行,我存储的是上三角
if(i<j)
{
q[e].u=i; q[e].v =j; q[e++].w=dd; //记录到结构体当中
}
}
} //
sort(q+0, q+e); //对结构体数组进行排序,边权小的靠前排序
for(i=0; i<=n; i++)
{
fa[i]=i; //并查集数组初始化,初始指向自己
}
scanf("%d", &m); //读入m条边
while(m--)
{
scanf("%d %d", &u, &v);
fa[findset(u)] = findset(v); //表示u和v已经有路径相同不需要再修建道路,所以在并茶几上把他们并到一个子集里
}
int ans=0; //用来记录最后还需要修建的路径总长度
for(int k=0; k<e; k++)
{
if(findset(q[k].u)!=findset(q[k].v) ) //如果这个结构体元素存储的两条村庄不属于同一个子集
{
fa[fa[q[k].u]] = fa[q[k].v]; //把这村庄合并到一个子集里 或者称合并到一棵树上
ans+=q[k].w;
}
}
printf("%d\n", ans ); //此代码还可以时间上优化一下,就是从输入m条边开始就统计已经加入生成树的边数,定义一个计数变量,当计数变量的值==n-1时就可以跳出上面的循环了
return 0;
}
这是从《数据结构 编程实验》那本书上看到的代码:用java写的,感觉并查集用的不错,但是在找边的时候的三层循环实在是不太好,时间性能太差,又很有没必要的循环
改写成结构体数组还是比较好使的。
代码如下:
import java.util.*;
import java.io.Reader;
import java.io.Writer;
import java.math.*; //导入java下的工具包 public class Main{
public static void print(string x){ //输出最小生成树的边长和
System.out.print(x);
}
static int[] fa; //并查集数组
public static int findset(int x){
return fa[x]!=x?fa[x]=findset(fa[x]):x;
} //带压缩路径的并查集
public static void main(string[] argv){ //定义main函数的参数是一个字符串类型的数组argv
Scanner input = new Scanner(System.in); //定义java的标准输入
while(input.hasNextInt() ){ //多组测试
int N = input.nextInt();
int [][]p = new int [N+1][N+1]; //为邻接矩阵申请内存
for(int i=0; i<n; i++)
{
for(int j=0; j<n; j++)
{
p[i][j] = input.nextInt();
}
}
fa = new int[N+1]; //为并查集数组申请内存
for(int i=0; i<N; i++) fa[i]=i; //父节点指针指向自己 初始化
for(int m=intput.nextInt(); m>0; m-- )
{
fa[findset(input.nextInt()-1)] = findset(input.nextInt()-1); //建立父子关系
}
int ans=0; //新建公路的长度初始化
for(int k=1; k<=1000; k++)
{
for(int i=0; i<N; i++)
{
for(int j=0; j<N; j++)
{
if(p[i][j]==k && findset(i)!=findset(j) )
{
fa[fa[i]] = fa[j];
ans+=k;
}
}
}
}
print(ans+"\n");
}
}
}
POJ 2421 Constructing Roads (Kruskal算法+压缩路径并查集 )的更多相关文章
- POJ 2421 Constructing Roads(Kruskal算法)
题意:给出n个村庄之间的距离,再给出已经连通起来了的村庄.求把所有的村庄都连通要修路的长度的最小值. 思路:Kruskal算法 课本代码: //Kruskal算法 #include<iostre ...
- POJ 2421 Constructing Roads (最小生成树)
Constructing Roads Time Limit:2000MS Memory Limit:65536KB 64bit IO Format:%I64d & %I64u ...
- poj 2421 Constructing Roads 解题报告
题目链接:http://poj.org/problem?id=2421 实际上又是考最小生成树的内容,也是用到kruskal算法.但稍稍有点不同的是,给出一些已连接的边,要在这些边存在的情况下,拓展出 ...
- POJ 2421 Constructing Roads (最小生成树)
Constructing Roads 题目链接: http://acm.hust.edu.cn/vjudge/contest/124434#problem/D Description There ar ...
- POJ - 2421 Constructing Roads 【最小生成树Kruscal】
Constructing Roads Description There are N villages, which are numbered from 1 to N, and you should ...
- POJ - 2421 Constructing Roads (最小生成树)
There are N villages, which are numbered from 1 to N, and you should build some roads such that ever ...
- POJ 2421 Constructing Roads
题意:要在n个城市之间建造公路,使城市之间能互相联通,告诉每个城市之间建公路的费用,和已经建好的公路,求最小费用. 解法:最小生成树.先把已经建好的边加进去再跑kruskal或者prim什么的. 代码 ...
- [kuangbin带你飞]专题六 最小生成树 POJ 2421 Constructing Roads
给一个n个点的完全图 再给你m条道路已经修好 问你还需要修多长的路才能让所有村子互通 将给的m个点的路重新加权值为零的边到边集里 然后求最小生成树 #include<cstdio> #in ...
- Poj 2421 Constructing Roads(Prim 最小生成树)
题意:有几个村庄,要修最短的路,使得这几个村庄连通.但是现在已经有了几条路,求在已有路径上还要修至少多长的路. 分析:用Prim求最小生成树,将已有路径的长度置为0,由于0是最小的长度,所以一定会被P ...
随机推荐
- 《写给大忙人看的Java核心技术》 勘误
先附上十分讨喜的封面.这应该是爱丽丝梦游仙境里的那只兔子吧? 勘误表基于原版勘误表制作 链接 截止日期 2017-02-09 对应<写给大忙人看的Java核心技术>2016年1月第1次印刷 ...
- Unslider--入门篇
Unslider--入门篇 背景:因工作需求,需要完成一个图片轮播效果,因博主不是专业的前端开发人员,so google之,经过挑选最终选择使用Unslider插件完成工作. 一.Unslider插件 ...
- python结构语句(while,if)
一.基础语法 编码: 默认情况下,Python 3 源码文件以 UTF-8 编码,所有字符串都是 unicode 字符串 #!/usr/bin/env python # -*- coding:utf- ...
- T1079 回家 codevs
http://codevs.cn/problem/1079/ 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 白银 Silver~死坑 题目描述 Description 现在是晚 ...
- SQL2000数据库密码被替换,重置密码提示未能找到存储过程sp_password解决方案
利用windows身份验证进入查询分析器后在master数据库下运行如下脚本: create procedure sp_password @old sysname = NULL, -- the old ...
- 临远的spring security教程
为啥选择Spring Security 欢迎阅读咱们写的Spring Security教程,咱们既不想写一个简单的入门教程,也不想翻译已有的国外教程.咱们这个教程就是建立在咱们自己做的OA的基础上,一 ...
- Mac Ubuntu ----端口被占用
Mac下使用lsof(list open files)来查看端口占用情况,lsof 是一个列出当前系统打开文件的工具. 使用 lsof 会列举所有占用的端口列表: 1 $ lsof 使用less可以用 ...
- Javascript:如何调用全局变量?
怎样使用全局变量呢? window.globalVariableName 参考: https://blog.csdn.net/zyz511919766/article/details/7276089
- 自己动手实现浏览器,21天自制chromium:起手篇
转:https://zhuanlan.zhihu.com/p/29101613?utm_medium=social&utm_source=qq 大家好,我又来了.这篇是21天自制原子弹的姐妹篇 ...
- 【Todo】【读书笔记】Linux高性能服务器编程
在读 /Users/baidu/Documents/Data/Interview/服务器-检索端/<Linux高性能服务器编程.pdf> 其实之前读过,要面试了,需要温习. P260 So ...