网页
资讯
视频
图片
知道
文库
贴吧
地图
采购
进入贴吧
全吧搜索
吧内搜索
搜贴
搜人
进吧
搜标签
日
一
二
三
四
五
六
签到排名:今日本吧第
个签到,
本吧因你更精彩,明天继续来努力!
本吧签到人数:0
一键签到
成为超级会员,使用一键签到
一键签到
本月漏签
0
次!
0
成为超级会员,赠送8张补签卡
如何使用?
点击日历上漏签日期,即可进行
补签
。
连续签到:
天 累计签到:
天
0
超级会员单次开通12个月以上,赠送连续签到卡3张
使用连续签到卡
01月27日
漏签
0
天
c4droid吧
关注:
42,860
贴子:
262,803
看贴
图片
吧主推荐
游戏
1
2
下一页
尾页
67
回复贴,共
2
页
,跳到
页
确定
<<返回c4droid吧
>0< 加载中...
冒泡 算法之美
只看楼主
收藏
回复
ljt12138
高手寂寞
11
该楼层疑似违规已被系统折叠
隐藏此楼
查看此楼
吧里面好多人都对算法不屑一顾。现成的东西干嘛要重写一遍?然而算法却比我们想象的要美很多。
ljt12138
高手寂寞
11
该楼层疑似违规已被系统折叠
隐藏此楼
查看此楼
样例输入
5 3 1
1 3
2 4
3 5
1 2
样例输出
No
样例解释
1,2不是亲戚
ljt12138
高手寂寞
11
该楼层疑似违规已被系统折叠
隐藏此楼
查看此楼
看到这道题,很多人一下子就懵了。卧槽这是什么鬼?然而我们细想一下,关系其实可以用一个邻接矩阵来存储。
邻接矩阵被描述为n*n的矩阵,其中a[x][y]表示x,y的关系。是亲戚为1,否则为0。这样,数据结构就明朗了。
ljt12138
高手寂寞
11
该楼层疑似违规已被系统折叠
隐藏此楼
查看此楼
上一道题的矩阵可以写成
0 0 1 0 0
0 0 0 1 0
1 0 0 0 1
0 1 0 0 0
0 0 1 0 0
特别说明,自己到自己的为0。
ljt12138
高手寂寞
11
该楼层疑似违规已被系统折叠
隐藏此楼
查看此楼
>>>解法一<<<
这道题很容易想到用动态规划来做,求出两两之间的距离。若为无穷大则说明不连通。我们用很大的整数9999999999表示无穷大,建立一个二维数组dis[][]
这一道题就可以看成
dis
0 ∞ 1 ∞ ∞
∞ 0 ∞ 1 ∞
1 ∞ 0 ∞ 1
∞ 1 ∞ 0 ∞
∞ ∞ 1 ∞ 0
ljt12138
高手寂寞
11
该楼层疑似违规已被系统折叠
隐藏此楼
查看此楼
用三重循环枚举每一个点作为中间点的情况,两点间的距离是否能被更新。代码很容易写出。
for (k=1; k<=n; k++)
for (i=1; i<=n; i++)
for (j=1; j<=n; j++)
dis[i][j]=max(dis[i][j],dis[i][k]+dis[k][j])
//每一个k做中介
ljt12138
高手寂寞
11
该楼层疑似违规已被系统折叠
隐藏此楼
查看此楼
这样只要判断两点上距离是否小于设定的无穷大即可
ljt12138
高手寂寞
11
该楼层疑似违规已被系统折叠
隐藏此楼
查看此楼
这个算法的复杂度是O(n^3),查找的复杂度O(ask),总共O(n^3)。空间复杂度O(n^2)。时间和空间都不很好。因此我们来介绍第二种算法
>>>解法二<<<
稍微一想便知道,我们从某点出发只需要对这个矩阵进行一次遍历,就可以知道所有与他连通的点。其余的点就不连通。我们可以用简单的深度优先搜索来完成。
ljt12138
高手寂寞
11
该楼层疑似违规已被系统折叠
隐藏此楼
查看此楼
代码很好写,用递归进行深度优先搜索。
bool find[100000]={0}
//c++用memset清0
void dfs(int i){
find[i]=1;
for (int j=1; j<=n; j++){
if (!find[j]&&f[i][j])
dfs(j);
}
}
ljt12138
高手寂寞
11
该楼层疑似违规已被系统折叠
隐藏此楼
查看此楼
从ask的起点遍历,看终点是否find即可,时间复杂度O(ask*n*n),空间不变(矩阵)
ljt12138
高手寂寞
11
该楼层疑似违规已被系统折叠
隐藏此楼
查看此楼
这样的时间复杂度仍然很高。我们需要寻求一种新方法。
>>>解法三<<<
我们可以运用集合的知识来解决。把有亲戚关系的人合并到一个集合,只需要判断两人是否在一个集合中,就可以得出他们的亲戚关系。但是集合怎么实现呢?
ljt12138
高手寂寞
11
该楼层疑似违规已被系统折叠
隐藏此楼
查看此楼
我们可以用并查集的方法来做。并查集,顾名思义就是可以合并-查找的集合。通常,我们用一个数组来实现。a[100000]。现将a[i]=0(1<=i<=n),表示他们各自处在自己的集合中。遇到两个人p,q,就把a[p]=q,把他和他的所有元素指向q,也就是把它们合并成了一个集合。
ljt12138
高手寂寞
11
该楼层疑似违规已被系统折叠
隐藏此楼
查看此楼
查找时间复杂度O(lgn),合并O(1),提问O(lgn),总共O(nlgn+asklgn)
ljt12138
高手寂寞
11
该楼层疑似违规已被系统折叠
隐藏此楼
查看此楼
尽管这样复杂度已经很优了,但针对特殊设计的数据,仍然有可能超时。例如当数据成链状时,查找最坏复杂度为O(n),退化到O(n^2+ask*n)
ljt12138
高手寂寞
11
该楼层疑似违规已被系统折叠
隐藏此楼
查看此楼
我们考虑种优化方法,当合并两个集合的时候,并不是简单地将一个指向另一个,而是将它指向他另一个最终父结点,从而尽可能地避免链状结构。
long find(int x) {
if (a[x] == 0)
return x;
a[x] = find(a[x]);
return a[x];
}
登录百度账号
扫二维码下载贴吧客户端
下载贴吧APP
看高清直播、视频!
贴吧页面意见反馈
违规贴吧举报反馈通道
贴吧违规信息处理公示