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 ...
随机推荐
- Jackson转换JSON例子
Jackson可以轻松的将Java对象转换成json对象和xml文档,同样也可以将json.xml转换成Java对象. 前面有介绍过json-lib这个框架,在线博文:http://www.cnblo ...
- uva 11798 相对运动的最小最大距离
C Dog Distance Input Standard Input Output Standard Output Two dogs, Ranga and Banga, are running ra ...
- Delphi中的操作二进制文件的两个重要函数
Delphi中的操作二进制文件的两个重要函数 对于通过Byte数组进行文件操作的,在FTP中经常会使用到,我也是在Delphi调用Web Service进行文件的上传和下载时找到这两个函数的,挺好用的 ...
- codevs——T1860 最大数||洛谷——P1107 最大整数
http://codevs.cn/problem/1860/ || https://www.luogu.org/problem/show?pid=1107#sub 题目描述 Description 设 ...
- Java中获取项目根路径和类加载路径的7种方法
引言 在web项目开发过程中,可能会经常遇到要获取项目根路径的情况,那接下来我就总结一下,java中获取项目根路径的7种方法,主要是通过thisClass和System,线程和request等方法. ...
- 洛谷 P1034 矩形覆盖
P1034 矩形覆盖 题目描述 在平面上有nn个点(n \le 50n≤50),每个点用一对整数坐标表示.例如:当 n=4n=4 时,44个点的坐标分另为:p_1p1(1,11,1),p_2p2( ...
- axis2调用WSDL接口
public static JSONObject sendWsdl(String url,String xmlStr){ JSONObject res=new JSONObject(); try { ...
- python的分布式队列神器 Celery
pip search kafka可以搜索到很多kafka的python插件,选择一个大家用的比较多的 celery结合kafka使用 使用kafka扩展python logging集中式日志收集 re ...
- Wide & Deep Learning Model
Generalized linear models with nonlinear feature transformations (特征工程 + 线性模型) are widely used for l ...
- 用C++实现一个Log系统
提要 近期在写一些C++的图形代码,在调试和測试过程中都会须要在终端打印一些信息出来. 之前的做法是直接用 std::cout<<"Some Word"<< ...