zoukankan      html  css  js  c++  java
  • hdu 1232 畅通工程 解题报告

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1232

          并查集入门题。最近在学并查集,它无非包括三个操作:make_set(x)、union_set(x, y)和find_set(x)。

         make_set(x)的作用是使得每一个成员x自成一个只包含x的集合。

         union_set(x, y)的作用是使x和y合并成为一个新的集合,确定x和y的连通性。

         find_set(x)则是查找到x的祖先,这里用set[i]表示元素 i  的祖先,换句话说就是,包含x的集合(唯一)的代表,当然这个代表是集合中的某个成员。对于如何选择代表要具体问题具体分析,但是要注意,如果寻找某一动态集合的代表两次,且在两次之间不修改集合,那么两次得到的答案应该是相同的。

         并查集主要是用于确定无向图中连通子图的个数。这条题目实质上就是找出非连通子图的个数,对应的结果就是最少还需要建设的道路数目。

         

     1 #include <iostream>
     2 using namespace std;
     3 
     4 const int maxn = 1000;
     5 
     6 int set[maxn];
     7 
     8 int find_set(int x)
     9 {
    10     int t = x;
    11     while (x != set[x])
    12     {
    13         x = set[x];
    14     }
    15     int j;
    16     while (t != x)   // 路径压缩,其实这里不用也行,它是为了处理元素很多或整棵树变为一条链的情况的,可以减少时间复杂度
    17 { 18 j = set[t]; 19 set[t] = x; 20 t = j; 21 } 22 return x; 23 } 24 25 void union_set(int x, int y) 26 { 27 x = find_set(x); 28 y = find_set(y); 29 if (x != y) 30 set[x] = y; 31 } 32 33 int main() 34 { 35 int i, n, m, c1, c2; 36 while (scanf("%d%d", &n, &m) != EOF && n) 37 { 38 for (i = 1; i <= n; i++) // make_set(x) 39 { 40 set[i] = i; 41 } 42 for (i = 0; i < m; i++) 43 { 44 scanf("%d%d", &c1, &c2); 45 union_set(c1, c2); // 把c1和c2合并成一个集合,确定它们是连通的 46 } 47 int cnt = -1;
    48 for (i = 1; i <= n; i++) // 注意:cnt是从-1开始的。每个集合都有一个“代表”。假设如果只有一个集合,那么是不再需要建设道路的,至少要有两个代表,才需要建设一条道路
    49 { 50 if (set[i] == i) // 每得到一个集合的代表,就需要建设一条路,只有一个集合的不需要建设道路!
    51 cnt++; 52 } 53 printf("%d\n", cnt); 54 } 55 return 0; 56 }
  • 相关阅读:
    康复计划
    Leetcode 08.02 迷路的机器人 缓存加回溯
    Leetcode 38 外观数列
    Leetcode 801 使序列递增的最小交换次数
    Leetcode 1143 最长公共子序列
    Leetcode 11 盛水最多的容器 贪心算法
    Leetcode 1186 删除一次得到子数组最大和
    Leetcode 300 最长上升子序列
    Leetcode95 不同的二叉搜索树II 精致的分治
    Leetcode 1367 二叉树中的列表 DFS
  • 原文地址:https://www.cnblogs.com/windysai/p/3252091.html
Copyright © 2011-2022 走看看