zoukankan      html  css  js  c++  java
  • 05-树8 File Transfer (25分)

    题目描述

    We have a network of computers and a list of bi-directional connections. Each of these connections allows a file transfer from one computer to another. Is it possible to send a file from any computer on the network to any other?

    Input Specification:

    Each input file contains one test case. For each test case, the first line contains N (2≤N≤10000), the total number of computers in a network. Each computer in the network is then represented by a positive integer between 1 and N. Then in the following lines, the input is given in the format:

    I c1 c2  
    

    where I stands for inputting a connection between c1 and c2; or

    C c1 c2
    

    where C stands for checking if it is possible to transfer files between c1 and c2; or

    S
    

    where S stands for stopping this case.

    Output Specification:

    For each C case, print in one line the word "yes" or "no" if it is possible or impossible to transfer files between c1 and c2, respectively. At the end of each case, print in one line "The network is connected." if there is a path between any pair of computers; or "There are k components." where k is the number of connected components in this network.

    Sample Input 1:

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

    Sample Output 1:

    no
    no
    yes
    There are 2 components.
    

    Sample Input 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
    

    Sample Output 2:

    no
    no
    yes
    yes
    The network is connected.
    

    解题思路

    这道题是典型的并查集问题,我们可以用树来表示每一个集合,用树的根结点值来代表集合名,又根据这道题的输入数据,我们可以用一个数组实现这些树,数组的下标对应电脑标号减1,元素值为其父结点的下标,根结点的值为-结点数。由题可知,需要处理ICS三种情况。对于I来说,我们首先需要得到两个数据对应的集合,若不同则合并,若相同则不管。于是这就可以抽象成两个问题,即得到数据对应的集合与合并两个集合。对于C来说,我们只需得到两个数据对应的集合,若相同打印yes,否则打印no。对于S来说,我们只需遍历数组,统计值小于0的元素个数,然后根据情况打印不同的字符串。

    代码

    #include <stdio.h>
    
    #define MAXSIZE 10000
    
    typedef int SetName;            //用根结点的值表示集合
    typedef int SetType[MAXSIZE];   //用一个数组表示集合,下标是电脑标号减一,值是父结点的下标
    
    void init(SetType set, int N);
    SetName getSetName(SetType set, int v);
    void merge(SetType set, SetName root1, SetName root2);
    void checkConn(SetType set);
    void connection(SetType set);
    void checkSet(SetType set, int N);
    
    int main() {
        int N;
        char op;
        SetType set;
        scanf("%d
    ", &N);
        init(set, N);
        do {
            scanf("%c", &op);
            switch (op) {
                case 'C':
                    checkConn(set); break;
                case 'I':
                    connection(set); break;
                case 'S':
                    checkSet(set, N); break;
            }
        } while (op != 'S');
        return 0;
    }
    
    //将数组前N个数初始化为-1
    void init(SetType set, int N) {
        for (int i = 0; i < N; i++) {
            set[i] = -1;
        }
    }
    
    //得到下标v对应的集合名
    SetName getSetName(SetType set, int v) {
        for ( ; set[v] >= 0; v = set[v]);
        return v;
    }
    
    //求两个集合的并集,为了尽可能地降低集合高度,将结点数小的集合的根连到结点数大的集合的根
    void merge(SetType set, SetName root1, SetName root2) {
        if (set[root1] < set[root2]) {  //集合1结点更多
            set[root1] += set[root2];
            set[root2] = root1;
        } else {
            set[root2] += set[root1];
            set[root1] = root2;
        }
    }
    
    //判断两个值是否属于同一集合
    void checkConn(SetType set) {
        int a, b;
        scanf("%d %d
    ", &a, &b);
        SetName root1, root2;
        root1 = getSetName(set, a - 1);
        root2 = getSetName(set, b - 1);
        if (root1 == root2) printf("yes
    ");
        else printf("no
    ");
    }
    
    //将两个值对应的集合并起来
    void connection(SetType set) {
        int a, b;
        scanf("%d %d
    ", &a, &b);
        SetName root1, root2;
        root1 = getSetName(set, a - 1);
        root2 = getSetName(set, b - 1);
        if (root1 != root2) merge(set, root1, root2);
    }
    
    //统计根结点个数,根据情况输出
    void checkSet(SetType set, int N) {
        int count = 0;
        for (int i = 0; i < N; i++) {
            if (set[i] < 0) count++;
        }
        if (count == 1) printf("The network is connected.
    ");
        else printf("There are %d components.
    ", count);
    }
    
  • 相关阅读:
    正向代理和反向代理
    CFree5构建中止问题
    [转]Prototype核心成员的反思
    解决js文件乱码问题
    【WPF开发备忘】使用MVVM模式开发中列表控件内的按钮事件无法触发解决方法
    rem 搭配 less 适配
    中国近代史-蒋廷黻
    docker 生成镜像 上传到docker hub
    CMD 执行 Python 脚本 出现假死状态
    vue 创建项目的两种方式
  • 原文地址:https://www.cnblogs.com/AndyHY-Notes/p/12562663.html
Copyright © 2011-2022 走看看