博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
交通工具(并查集)
阅读量:4543 次
发布时间:2019-06-08

本文共 2328 字,大约阅读时间需要 7 分钟。

★实验任务

小z为竞选他们村的村长,他承诺在这个村上建其地下公路来方便大家出行。

但这个地下公路有一个奇怪的规定,每条公路上只能使用有限种交通工具,从出 发点到终点只能使用一种交通工具。现在小 z想知道从某点到另一点可以采用
多少种交通工具。
为简化起见,为地下公路的 N个点编号,分别为 0~N-1,地下公路的交通 工具一共 C种,编号为 1~C。

★数据输入

输入第一行包括两个整数,N,M,分别表示有 N个点,M条公路。接下来 M行,每行三个数 u,v,c,表示从 u到 v可以采用 c种交通工具。接着输入 Q,表示询问个数,接下来 Q行,每行两个数 p,q,表示查询从 p到 q有多少

种交通工具方式。

★数据输出

对于 Q个询问,分别输出每个询问的结果。

解题思路:看到题目之后,根据题目所描述的总共最多十种交通工具,然后判断每两个点之间有几种交通工具可以达到,可以每种交通工具下面都做一个并查集进行查询看这种交通工具是否可以使得两点联通;

并查集实现核心及易错细节:我一般通过数组的方式实现并查集,每个点都有一个fa,在数据比较小的时候可以直接通过一个fa数组存储每一个点的父亲节点,然后就是查询根节点和合并两棵子树(集合);

查询过程:有直接每次递归查询,可根据题目需要,判断是否需要在递归过程中压缩路径(在只需要找到每个点的根节点的时候压缩路径肯定会减小查询时间的,但是如果还需要精确到每条路径怎么走的时候就不能压缩路径了)

int find_Fa(int tran, int roa){    if (fa[tran][roa] != roa) { fa[tran][roa] = find_Fa(tran, fa[tran][roa]); }    return fa[tran][roa];           //通过递归返回的方式将路径压缩}

合并过程:在每次对两个节点判断做合并的时候可以通过对该节点的高度判断哪棵树合并到另一棵树下面

void uni(int tran,int r1,int r2){    r1 = find_Fa(tran, r1), r2 = find_Fa(tran, r2);    if (r1 == r2)return;    if (hei[tran][r1] > hei[tran][r2])fa[tran][r2] = r1;    else    {        fa[tran][r1] = r2;        if (hei[tran][r1] == hei[tran][r2])hei[tran][r2]++;    }}

我出现的错误:在合并的时候直接用的是fa[r1]和fa[r2]没有对他们进行搜索根节点,导致整个过程一直出错;

此题代码:

#include
#include
int fa[11][105];int hei[11][105] = { 0 };int find_Fa(int tran, int roa){ if (fa[tran][roa] != roa) { fa[tran][roa] = find_Fa(tran, fa[tran][roa]); } return fa[tran][roa]; //通过递归返回的方式将路径压缩}void uni(int tran,int r1,int r2){ r1 = find_Fa(tran, r1), r2 = find_Fa(tran, r2); if (r1 == r2)return; if (hei[tran][r1] > hei[tran][r2])fa[tran][r2] = r1; else { fa[tran][r1] = r2; if (hei[tran][r1] == hei[tran][r2])hei[tran][r2]++; }}int main(){ int n, m, i, j, roa1, roa2, tran; scanf("%d%d", &n, &m); for (i = 1; i < 11; i++) { for (j = 0; j < n; j++) { fa[i][j] = j; } } for (i = 0; i < m; i++) { scanf("%d%d%d", &roa1, &roa2, &tran); uni(tran, roa1, roa2); } int que, sum = 0; scanf("%d", &que); for (i = 0; i < que; i++) { sum = 0; scanf("%d%d", &roa1, &roa2); for (j = 1; j <= 10; j++) { if (find_Fa(j, roa1) == find_Fa(j, roa2))sum++; } printf("%d\n", sum); } return 0;}

并查集还需要多加练习;

转载于:https://www.cnblogs.com/heihuifei/p/8029737.html

你可能感兴趣的文章
设计模式-注册树模式
查看>>
Vim有哪几种模式?
查看>>
Unity基本API总览
查看>>
如何将一段文本编译成C#内存程序的过程
查看>>
PAT——1070. 结绳
查看>>
【23.33%】【codeforces 664C】International Olympiad
查看>>
java-网络编程-使用URLDecoder和URLEncoder
查看>>
最短路之dijkstra算法
查看>>
SHDP--Working With HBase (二)之HBase JDBC驱动Phoenix与SpringJDBCTemplate的集成
查看>>
Lua语法基础(一)
查看>>
.Net Core2.*学习手册
查看>>
实验一、命令解释程序的编写实验
查看>>
2018年11月14日 学习字符串用法2
查看>>
2019年5月26日 re模块2
查看>>
Python学习笔记(一)——初学Python
查看>>
顺序表应用8:最大子段和之动态规划法(SDUT 3665)
查看>>
Python内置函数(52)——range
查看>>
正则表达式
查看>>
c# 执行 sql service 的存储过程
查看>>
《软件构架实践》读后感03
查看>>