PTA File Transfer

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≤10​4​​), 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:

 

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

 

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

 

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 kcomponents." where k is the number of connected components in this network.

 

解题思路:该题主要设计到集合间的合并与搜索,需要找到一个数据结构去存放结点间的联系。(PTA上这题是放在堆的一章里面的,可能囿于旧思维,我想不到这题与堆这个结构的联系(仅有的一点联系就是同样用数组来存储?),还请大家不吝赐教。

  比较巧妙的一点是利用是否同根来判断两个结点是否为同一个集合,而寻找同根的方式为压缩路径维护这课树的深度的方式为按秩归并

  使用一个数组来存储编号的父节点

  find函数返回父节点  

int find(int num)//路径压缩
{
    return fa[num]==0?num:find(fa[num]);
}

 运用按秩归并的方式压缩树的深度,也就是说将秩(rank)大的树作为主根节点,这样可以有效避免树的深度不断增加。

  需要指出的是,查看了网上的文章后,大家都没有显式的指出按秩归并的相较于普通归并的优势,这里先讲一下我之前的思路是路径压缩查出根节点后按根节点大小进行连接,这样导致了既定一种排序方式后(如根大连在根小的下面)数据相反顺序输入时,会导致树的深度线性增加。而采用按秩归并则避免了这个情况,因为永远是连在秩大的根下面。

//按秩归并
if(rank[root1]rank[root2])
    {
        fa[root2]=root1;
        rank[root1]++;
        num--;
    }
    else
    {
        fa[root1]=root2;
        rank[root2]++;
        num--;
    }

 

最终代码:

#include 
void check(void);
void initial(void);
int find(int);
int fa[10005],rank[10005],num;
int main(void)
{
    char ch;
    scanf("%d",&num);
    while((ch=getchar())!='S')
    {
        switch (ch) {
            case 'C':
                check();
                break;
            case 'I':
                initial();
            default:
                break;
        }
    }
    if(num==1)
        printf("The network is connected.\n");
    else
        printf("There are %d components.\n",num);
}

void check(void)
{
    int num1,num2;
    scanf("%d %d",&num1,&num2);
    int root1=find(num1);
    int root2=find(num2);
    if(root1==root2)
        printf("yes\n");
    else
        printf("no\n");
}

void initial(void)
{
    int num1,num2;
    scanf("%d %d",&num1,&num2);
    int root1=find(num1);
    int root2=find(num2);
    if(root1==root2)
        return;
    if(rank[root1]rank[root2])
    {
        fa[root2]=root1;
        rank[root1]++;
        num--;
    }
    else
    {
        fa[root1]=root2;
        rank[root2]++;
        num--;
    }
}

int find(int num)
{
    return fa[num]==0?num:find(fa[num]);
}








最后附上测试数据,

https://img-blog.csdn.net/20161003210307030?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center (摘自CSDN的博主时间杀手Time的文中)

你可能感兴趣的:(数据结构)