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 }
  • 相关阅读:
    Kubernetes 再深入一点点
    10分钟完成 mongodb replSet 部署
    网络篇
    p2p 打洞专场(转)
    Dockerfile 编写
    关于github 代码管理,协作开发
    Kubernetes 基于 ubuntu18.04 手工部署 (k8s)
    备忘 ubuntu ip 及 dns 的坑
    各种语言web性能简单对比测试
    vue 按需加载
  • 原文地址:https://www.cnblogs.com/windysai/p/3252091.html
Copyright © 2011-2022 走看看