• 关于并查集问题


    因为从来没有接触过并查集,但是前几天测试中出现了并查集的题,我也开始关注了起来,并且经过几天的研究终于搞懂了.以下是当时的题

    7-4 文件传输 (25 分)

    当两台计算机双向连通的时候,文件是可以在两台机器间传输的。给定一套计算机网络,请你判断任意两台指定的计算机之间能否传输文件?

    输入格式:

    首先在第一行给出网络中计算机的总数 N (2N104​​),于是我们假设这些计算机从 1 到 N 编号。随后每行输入按以下格式给出:

    I c1 c2  
    

    其中I表示在计算机c1c2之间加入连线,使它们连通;或者是

    C c1 c2    
    

    其中C表示查询计算机c1c2之间能否传输文件;又或者是

    S
    

    这里S表示输入终止。

    输出格式:

    对每个C开头的查询,如果c1c2之间可以传输文件,就在一行中输出"yes",否则输出"no"。当读到终止符时,在一行中输出"The network is connected."如果网络中所有计算机之间都能传输文件;或者输出"There are k components.",其中k是网络中连通集的个数。

    输入样例 1:

    5
    C 3 2
    I 3 2
    C 1 5
    I 4 5
    I 2 4
    C 3 5
    S
    

    输出样例 1:

    no
    no
    yes
    There are 2 components.
    

    输入样例 2:

    5
    C 3 2
    I 3 2
    C 1 5
    I 4 5
    I 2 4
    C 3 5
    I 1 3
    C 1 5
    S
    

    输出样例 2:

    no
    no
    yes
    yes
    The network is connected.
    
     
    作者: 陈越
    单位: 浙江大学
    时间限制: 150 ms
    内存限制: 64 MB
    代码长度限制: 16 KB

     这道题乍一看我想到的是DFS,但是在向下继续写的过程中便暴露了很多问题,知道我搞懂了并查集,才发现这题是这么简单

    以下是我的代码:

     1 #include<stdio.h>
     2 int pre[10000];//当时少了一个0得注意
     3 int find(int x){
     4     if(pre[x]!=x){
     5         pre[x] = find(pre[x]); //如果自己的老大不是自己,那么就递归继续寻找老大 
     6     }
     7     return pre[x]; //找到老大就返回 
     8 } 
     9 void join(int x,int y){
    10     int fx = find(x);
    11     int fy = find(y);
    12     if(fx!=fy){
    13         pre[fx] =  fy; //将两个不同的老大连通 
    14     }
    15 }
    16 int main()
    17 {
    18     int n;     //一共多少台电脑 
    19     char s;   //状态 
    20     int a,b;  //电脑名称 
    21     int i,j,k;//循环变量 
    22     scanf("%d",&n);
    23     for(i=0;i<n;i++){
    24         pre[i] = i;//初始化电脑状态,每个人都只是与自己连通 
    25     }
    26     while(~scanf("%c",&s)){
    27         if(s=='S'){
    28             break;//输入S程序结束 
    29         }
    30         scanf("%d %d",&a,&b);//我习惯从0开始 
    31         if(s=='C'){ //查询 
    32             if(find(a-1)==find(b-1)){
    33                 printf("yes
    "); //说明两个老大一样,所以连通 
    34             }else{
    35                 printf("no
    ");
    36             }
    37         }
    38         if(s=='I'){//如果两台机子不连通就让他们连通 
    39             join(a-1,b-1); 
    40         }
    41     }
    42     int cut=0;
    43     for(i=0;i<n;i++){
    44         if(find(i)==i){
    45             cut++;
    46         }
    47     }
    48     if(cut==1)printf("The network is connected.");//如果只有一个老大说明大家都连通
    49     else printf("There are %d components.",cut); 
    50 }

    通过这道题,我感觉我要学的东西还有很多,我会一点一点继续学习更多的知识的.

  • 相关阅读:
    FAQs: 当在Outlook Explorer中右击邮件时,如何向上下文菜单添加按钮?(VSTO技术)
    C#设置系统日期和时间
    控制带有滚动条的控件(ListView,TreeView等)的滚动条显示
    HTML Clipboard Format [MSDN资料]
    Control.ProcessDialogKey 方法 ——用以处理对话框按键(TAB ESC 箭头键 等)
    span 标记的可编辑与不可编辑
    教训:System.TypeInitializationException 类型初始值设定项引发异常
    firefox 插件制作
    base64编码
    找工作了,应聘简历
  • 原文地址:https://www.cnblogs.com/wysAC666/p/9676075.html
Copyright © 2020-2023  润新知