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 ...
随机推荐
- kubernetes---CentOS7安装kubernetes1.11.2图文完整版
转载请注明出处:kubernetes-CentOS7安装kubernetes1.11.2图文完整版 架构规划 k8s至少需要一个master和一个node才能组成一个可用集群. 本章我们搭建一个mas ...
- 淘金(bzoj 3131)
Description 小Z在玩一个叫做<淘金者>的游戏.游戏的世界是一个二维坐标.X轴.Y轴坐标范围均为1..N.初始的时候,所有的整数坐标点上均有一块金子,共N*N块. 一阵风吹 ...
- 费用流(bzoj 3130)
Description Alice和Bob在图论课程上学习了最大流和最小费用最大流的相关知识. 最大流问题:给定一张有向图表示运输网络,一个源点S和一个汇点T,每条边都有最大流量.一个合法的网络 ...
- 1109 NOIP 模拟考试
NOIP2016 模拟赛 ——那些年,我们学过的文化课 背单词(word.c/cpp/pas)[题目描述]fqk 退役后开始补习文化课啦, 于是他打开了英语必修一开始背单词. 看着满篇的单词非常头疼, ...
- AtCoder Grand Contest 005F - Many Easy Problems
$n \leq 200000$的树,从树上选$k$个点的一个方案会对$Ans_k$产生大小为“最小的包括这$k$个点的连通块大小”的贡献.求每个$Ans_k$.膜924844033. 看每个点对$An ...
- R语言入门---杂记(一)---R的常用函数
1.nchar():查看字符串长度. 2.rev(): 给你的数据翻个个 3.sort():给你数据排个序(默认从小到大依次排列) 4.runif():产生均匀分布的随机数 #runif
- Laravel 控制器的middleware中间件
场景:活动开始前只能访问宣传页面,开始后才可以访问其他页面: 步骤: 新建中间件, 注册中间件, 使用中间件, 中间件的前置和后置操作. 控制器: public function activity0( ...
- H5 折线图插件
一.可以使用Highcharts,参考网址:https://api.hcharts.cn/highcharts: 二.可以使用Echarts,参考网址:http://echarts.baidu.com ...
- 省赛i题/求1~n内所有数对(x,y),满足最大公约数是质数的对数
求1~n内所有数对(x,y),gcd(x,y)=质数,的对数. 思路:用f[n]求出,含n的对数,最后用sum[n]求和. 对于gcd(x,y)=a(设x<=y,a是质数),则必有gcd(x/a ...
- nginx的配置文件 【nginx.conf】
#user nobody; worker_processes 1; #error_log logs/error.log; #error_log logs/error.log notice; #erro ...