NOJ [1274] The battle of Red Cliff

本文讨论了如何利用并查集算法解决赤壁之战问题。通过建立节点关系和合并集合,实现了对不同学生之间的社交关系进行统一管理。详细介绍了并查集的基本概念、数据结构、操作方法,并通过实例演示了算法的具体应用。
赤壁之战
链接地址:http://ac.nbutoj.com/Problem/view.xhtml?id=1274

本题的算法为并查集。
所谓并查集,就是将相同类型的几个单位并在一起。
例如交朋友,只要一个人跟另一个人成为了朋友,他们都会把彼此的朋友介绍给对方。
现在有10个彼此陌生的学生,编号分别为1到10.
X Y
1 2
3 4
5 6
7 8
9 10
1 3
5 7
以上的输入表示编号X与编号Y的学生成为了朋友。
那么,我们可以知道,(1,2,3,4)为一组,(5,6,7,8)为一组,(9,10)为一组。
然后并查集的思想就是将这些节点建立在一棵树上。
我们可以通过一个数组v[],一开始每个人都没有朋友,那么这个数组初始化时,可以将每个位置的数都赋值为本身。for(i=1;i<=n;i++) v[i] = i;
此数组的作用就是来存他的父节点。
例如上面的输入:
v[]     1  2  3  4  5  6  7  8  9  10
before: 1  2  3  4  5  6  7  8  9  10
next  : 2  4  4  4  6  8  8  8  10 10
这里v[0]是不参与的。
现在v数组里存的都是他父节点的数。
用find()函数来寻找他的父节点。

int find(int x)
{
    if (v[x] != x) v[x] = find(v[x]);
    return v[x];
}
我们用rank[]数组来保存阶级,初始化全为0.
用Union()函数来将两个点的集合合并。

void Unoin(int x, int y)
{
    if (rank[x] > rank[y]) v[y] = x;
    else if (rank[x] < rank[y]) v[x] = y;
    else
    {
        v[x] = y;
        rank[y]++;
    }
}

最后输入一个数代表要烧的船的编号,求出剩下船只的数量、
所以我们只要把总数量减去这个编号所在的集合里的船只数量,得到的就是答案。

代码就不贴了。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值