HDU1232 畅通工程

来源:互联网 发布:订单系统代码java 编辑:程序博客网 时间:2024/06/04 01:07

这题使用并查集来解决,先贴上代码:

#define LOCAL#include <iostream>#include <fstream>#include <vector>#include <algorithm>#include <utility>using namespace std;#define MAX_N 1005int _par[MAX_N];                // 父亲int _rank[MAX_N];               // 树的高度// 初始化n个元素void init(int n){    for (int i = 0; i < n; i++)    {        _par[i] = i;        _rank[i] = 0;    }}// 查询树的根int find(int x){    if (_par[x] == x)        return x;    else        return _par[x] = find(_par[x]);}// 合并x和y所属的集合void unite(int x, int y){    x = find(x);    y = find(y);    if (x == y) return;    if (_rank[x] < _rank[y]) {        _par[x] = y;    }    else {        _par[y] = x;        if (_rank[x] == _rank[y])            _rank[x]++;    }}// 判断x和y是否属于同一个集合bool same(int x, int y){    return find(x) == find(y);}int main(){#ifdef LOCAL    freopen("input.txt", "r", stdin);    //  freopen("output.txt", "w", stdout);#endif    int N, M;    while (cin >> N >> M && N) {        for (int i = 0; i < N; ++i)            _par[i] = i;        init(N);        while (M--)        {            int x, y;            cin >> x >> y;            unite(x, y);        }        int num = -1;        for (int j = 1; j <= N; ++j)            if (_par[j] == j)                num++;        cout << num << endl;    }    return 0;}

这是我之前贴在GitHub上的代码,今天翻以前校赛的题发现了这个就重新拿出来再看一看。并查集的这个代码是我从《挑战程序设计》上面抄下来的,集合了很多并查集的操作,可以直接使用。

======================更新======================
明白了如下代码段的用意:

for (int j = 1; j <= N; ++j)    if (_par[j] == j)        num++;

_par[j]中存储了每个节点的父亲节点,因为并查集的查找操作就是逐层向上找到祖先判断两个节点是否是同一祖先就判断出了是否是属于同一结合,所以如果某个节点的祖先如果是自己,那么说明这是一个联通分量,当联通分量为1的时候,num++结果为0,正好说明不需要修路。所以每增加一个连通分量,就要多修一条路以保证畅通,所以判断j的父节点是否等于j就可以找出连通分量的个数。

0 0
原创粉丝点击