• hrbustoj 1073:病毒(并查集,入门题)


    病毒
    Time Limit: 1000 MS Memory Limit: 65536 K
    Total Submit: 719(185 users) Total Accepted: 247(163 users) Rating: Special Judge: No
    Description
    某种病毒袭击了某地区,该地区有N(1≤N≤50000)人,分别编号为0,1,...,N-1,现在0号已被确诊,所有0的直接朋友和间接朋友都要被隔离。例如:0与1是直接朋友,1与2是直接朋友,则0、2就是间接朋友,那么0、1、2都须被隔离。现在,已查明有M(1≤M≤10000)个直接朋友关系。如:0,2就表示0,2是直接朋友关系。
    请你编程计算,有多少人要被隔离。

    Input
    第一行包含两个正整数N(1≤N≤50000),M(1≤M≤100000),分别表示人数和接触关系数量;
    在接下来的M行中,每行表示一次接触,;
    每行包括两个整数U, V(0 <= U, V < N)表示一个直接朋友关系。

    Output
    输出数据仅包含一个整数,为共需隔离的人数(包含0号在内)。

    Sample Input
    100 4
    0 1
    1 2
    3 4
    4 5

    Sample Output
    3


      并查集,入门题

      思路是先根据关系建立关系树,然后记录0号小朋友的根节点,依次与剩下所有的小朋友的根节点比较,相等则计数+1,表示这是和0号小朋友有关系的,即被感染的人。最后输出总计数(即被0号小朋友感染的人数)。

      套模板很容易过。

      代码:

     1 #include <stdio.h>
     2 
     3 /* 并查集模板
     4 */
     5 int UFS_NUM;    //并查集中元素总数
     6 typedef struct node{
     7     int data;    //节点对应的编号 
     8     int rank;    //节点对应秩 
     9     int parent;    //节点对应的双亲下标 
    10 }UFSTree;        //并查集树的节点类型 
    11 void MAKE_SET(UFSTree t[])    //初始化并查集树 
    12 {
    13     int i;
    14     for(i=0;i<UFS_NUM;i++){
    15         t[i].data = i;        //数据为该点编号 
    16         t[i].rank = 0;        //秩初始化为0 
    17         t[i].parent = i;    //双亲初始化为指向自己 
    18     }
    19 }
    20 int FIND_SET(UFSTree t[],int x)    //在x所在的子树中查找集合编号
    21 {
    22     if(t[x].parent == x)    //双亲是自己 
    23         return x;    //双亲是自己,返回 x 
    24     else    //双亲不是自己 
    25         return FIND_SET(t,t[x].parent);    //递归在双亲中查找x 
    26 } 
    27 void UNION(UFSTree t[],int x,int y)    //将x和y所在的子树合并
    28 {
    29     x = FIND_SET(t,x);    //查找 x 所在分离集合树的编号 
    30     y = FIND_SET(t,y);    //查找 y 所在分离集合树的编号 
    31     if(t[x].rank > t[y].rank)    //y 节点的秩小于 x节点的秩 
    32         t[y].parent = x;        //将 y 连接到 x 节点上,x 作为 y 的双亲节点 
    33     else{                //y 节点的秩大于等于 x 节点的秩 
    34         t[x].parent = y;            //将 x 连接到 y 节点上,y 作为 x 的双亲节点 
    35         if(t[x].rank==t[y].rank)    //x 和 y的双亲节点秩相同 
    36             t[y].rank++;            //y 节点的秩增 1 
    37     }
    38 } 
    39 int main()
    40 {
    41     int i,n,m,x,y;
    42     while(scanf("%d%d",&n,&m)!=EOF){
    43         UFSTree t[50005];
    44         UFS_NUM = n;
    45         MAKE_SET(t);
    46         for(i=1;i<=m;i++){
    47             scanf("%d%d",&x,&y);
    48             UNION(t,x,y);
    49         }
    50         int f0 = FIND_SET(t,0);
    51         int sum=0;
    52         for(i=0;i<n;i++)
    53             if(FIND_SET(t,i)==f0)
    54                 sum++;
    55         printf("%d
    ",sum);
    56     }
    57     return 0;
    58 }

    Freecode : www.cnblogs.com/yym2013

  • 相关阅读:
    实时控制软件设计第一周作业-汽车ABS软件系统案例分析
    团队项目·冰球模拟器——任务间通信、数据共享等设计
    团队项目·冰球模拟器——cmake 自动化构建系统的配置文件的编写
    团队项目·冰球模拟器——文件结构设计
    团队项目·冰球模拟器——插值算法接口设计
    第四周作业
    第三周作业、实时操作系统µC/OS介绍及其它内容
    第二周作业、停车场门禁控制系统状态机
    Open Dynamics Engine for Linux 安装笔记
    第一周作业、典型实时控制系统案例分析
  • 原文地址:https://www.cnblogs.com/yym2013/p/3691823.html
Copyright © 2020-2023  润新知