• 并查集


    SZU Problem(A70):Locked Boxes

    Judge Info

    • Memory Limit: 32768KB
    • Case Time Limit: 10000MS
    • Time Limit: 10000MS
    • Judger: Number Only Judger

    Description

    Poseidon has N boxes with lock. What's inside the box? (hum..., think by yourself) Each box can either be opened with its corresponding key or smashed. Poseidon has put the keys in some of the boxes. He remembers which key has been placed in which box. Poseidon wants to access to all of the boxes. However, he wants to destroy as few of them as possible. Please write a Program to help Poseidon to determine how many boxes have to be smashed.

    Input

    The input will contains multiple test cases. The first line of the input is a single integer T (1 leq T leq 30) which is the number of test cases. T test cases follow.

    Each test case contains a single integer N (1 leq N leq 1,000,000) - this is the number of boxes owned by Poseidon. The boxes (as well as their corresponding keys) are numbered from 1 to N. Next, there are N lines: the i+1st line contains a single integer - the number of the box which the ith key has been placed in.

    Output

    For each input test case, you are to output a single integer - the minimal number of boxes to be smashed in order to access to all of the boxes.

    Sample Input

    2
    
    4
    2
    1
    2
    4
    
    4
    2
    1
    2
    4
    

    Sample Output

    2
    2
     1 #include <stdio.h>
     2 #define N 1000010
     3 int array[N];  // 用来记录箱子的钥匙在哪里
     4 int search( int );
     5  
     6 int main()
     7 {
     8     int t, n, i, a;
     9     int num = 0; // 计算需要打烂多少个箱子
    10     scanf( "%d", &t );
    11     while( t-- )
    12     {
    13         scanf( "%d", &n );
    14         // 初始化
    15         for( i=1; i<=n; i++ )
    16             array[i] = i;
    17         num = 0;
    18         // 输入箱子的钥匙在哪里并判断它的根是谁。。
    19         for( i=1; i<=n; i++ )
    20         {
    21             scanf( "%d", &a );
    22             array[i] = search(a);
    23             if( array[i] == i )
    24                 num++;
    25         }
    26         printf( "%d
    ", num );
    27     }
    28     return 0;
    29 }
    30  
    31 int search( int i )
    32 {
    33     int key = i;
    34     // 找根
    35     while( array[i] != i )
    36         i = array[i];
    37     // 路径压缩
    38     int root = i;
    39     int t = key;
    40     int temp;
    41     while( array[t] != t )
    42     {
    43         temp = array[t];
    44         array[t] = root;
    45         t = temp;
    46     }
    47     return root;
    48 }

    SZU Problem(B36):Reading books

    Judge Info

    • Memory Limit: 32768KB
    • Case Time Limit: 10000MS
    • Time Limit: 10000MS
    • Judger: Number Only Judger

    Description

    In the summer vacation, LRJ wants to improve himself in computer science. So he finds out N books of computer science in the school library. The books are numbered from 0 to N-1.

    To finish reading the i-th book, it takes LRJ time[i] minutes. But some books are similar in the content. If the i-th book and the j-th book are similar, then if LRJ has finished reading the i-th book, it will take him only left lfloor frac{time[j]}{2} 
ight 
floor minutes to finish reading the j-th book. Of course if LRJ has finished reading the j-th book, it will take him only left lfloor frac{time[i]}{2} 
ight 
floor minutes to finish reading the i-th book. Now you are asked to tell LRJ the minimal total time to finish reading all the N books.

    Input

    The first line contains two integers N(0leq N leq 100) and M(0leq M leq N	imes (N-1)/2). N is the total number of books. M is the number of pairs which are similar.

    Then the following N lines describe time[0],time[1],cdots,time[n-1](1leq time[i] leq 10^{5}).

    Next comes M lines, each contains two integer (i,j), indicating that the i-th book and the j-th book are similar.

    Input is ended with EOF.

    Output

    For each test case, just output the minimal total time on a single line.

    Sample Input

    2 1
    6
    10
    0 1
    3 2
    1
    2
    3
    0 1
    1 2
    3 1
    2
    4
    6
    0 1
    

    Sample Output

    11
    3
    10
     1 #include <stdio.h>
     2 #define N 110
     3 #define M 5000
     4 int time[N];
     5 int array[M];
     6 int sum[N]; // 按秩分配
     7 int search( int );
     8 int main()
     9 {
    10     int n, m;
    11     int i;
    12     int a, b;
    13     int total;
    14     while( scanf("%d%d", &n, &m ) != EOF )
    15     {
    16         total = 0;
    17         for( i=0; i<n; i++ )
    18         {
    19             scanf( "%d", &a );
    20             time[i] = a;
    21             sum[i] = time[i]/2;
    22         }
    23         for( i=0; i<n; i++ )
    24             array[i] = i;
    25         i = 0;
    26         while( i < m )
    27         {
    28             scanf( "%d%d", &a, &b );
    29             // 记得比较祖先~~~
    30             a = search(a);
    31             b = search(b);
    32             i++;
    33             // 记得考虑两者拥有共同祖先的时候!!!
    34             if( a == b )
    35                 continue;
    36             if( time[a] <= time[b] )
    37             {
    38                 array[b] = a;
    39                 sum[a] += sum[b];
    40             }
    41             else
    42             {
    43                 array[a] = b;
    44                 sum[b] += sum[a];
    45             }
    46         }
    47         for( i=0; i<n; i++ )
    48             if( array[i] == i )
    49             {
    50                 sum[i] = sum[i] - time[i]/2 + time[i];
    51                 total += sum[i];
    52             }
    53         printf( "%d
    ", total );
    54     }
    55     return 0;
    56 }
    57  
    58 int search( int i )
    59 {
    60     int t = i;
    61     // 找根
    62     while( array[i] != i )
    63         i = array[i];
    64     // 路径压缩
    65     int root = i;
    66     int temp;
    67     while( array[t] != t )
    68     {
    69         temp = array[t];
    70         array[t] = root;
    71         t = temp;
    72     }
    73     return root;
    74 }

    SZU Problem(B64):Network Connections

    Judge Info

    • Memory Limit: 32768KB
    • Case Time Limit: 10000MS
    • Time Limit: 10000MS
    • Judger: Normal

    Description

    Bob, who is a network administrator, supervises a network of computers. He is keeping a log connections between the computers in the network. Each connection is bi-directional. Two computers are interconnected if they are directly connected or if they are interconnected with the same computer. Occasionally, Bob has to decide, quickly, whether two given computers are connected, directly or indirectly, according to the log information.

    Write a program which based on information input from a text file counts the number of successful and the number of unsuccessful answers to the questions of the kind : is computer i \, interconnected with computer j\, ?

    Input

    The first line of the input contains the number of dataset, and it's followed by a blank line. Each dataset is defined as follows:

    • The number of computers in the network N\,(N leq 10,000);
    • A list of pairs of the form:
      • c\, computer i\, computer j\,, where computer i\, and computer j\, are integers from 1\, to N\,. A pair of this form shows that computer i\, and computer j\, get interconnected.
      • q\, computer i\, computer j\,, where computer i\, and computer j\, are integers from 1\, to N \,. A pair of this form stands for the question: is computer i\, interconnected with computer j\,?

    There's a blank line between datasets.

    Each pair is on a separate line. Pairs can appear in any order, regardless of their type. The log is updated after each pair of type (a) and each pair of type (b) is processed according to the current network configuration.

    Output

    For example, the input file illustrated in the sample below corresponds to a network of 10 computers and 7 pairs. There are N1\, successfully answered questions and N2\, unsuccessfully answered questions. The program prints these two numbers to the standard output on the same line, in the order: successful answers, unsuccessful answers, as shown in the sample output. Print a blank line between datasets.

    Sample Input

    1
    
    10
    c 1 5
    c 2 7
    q 7 1
    c 3 9
    q 9 6
    c 2 5
    q 7 5
    

    Sample Output

    1,2
    血的教训,能用getchar(), 决不用scanf( "%c", &c );
     1 #include <stdio.h>
     2 #define N 10005
     3 int array[N];
     4 int findroot( int );
     5  
     6 int main()
     7 {
     8     int t, a, b, i, n, yes, no;
     9     char request;
    10     scanf( "%d", &t );
    11     while( t-- )
    12     {
    13         scanf( "%d
    ", &n );
    14         // 初始化啊,我是石头里蹦出来的,自己爸爸的是自己^^
    15         for( i=1; i<=n; i++ )
    16             array[i] = i;
    17         yes = no = 0;
    18         while( request = getchar() )
    19         {
    20             // 手拉手我们是好朋友
    21             if( request == 'c' )
    22             {
    23                 scanf( "%d%d", &a, &b );
    24                 if( findroot(a) != findroot(b) ) // 判断是否同祖先
    25                     array[findroot(a)] = findroot(b);
    26             }
    27             // 问呀问呀问问题
    28             else if( request == 'q' )
    29             {
    30                 scanf( "%d%d", &a, &b );
    31                 if( a == b )
    32                     yes++;
    33                 else
    34                 {
    35                     if( findroot(a) == findroot(b) )
    36                         yes++;
    37                     else
    38                         no++;
    39                 }
    40             }
    41             else  // 最后一个不判断
    42                 break;
    43             getchar();
    44         }
    45         printf( "%d,%d
    ", yes, no );
    46         if( t )
    47             printf( "
    " );
    48     }
    49     return 0;
    50 }

    SZU  Problem(J21):Are they the same?

    Judge Info

    • Memory Limit: 65536KB
    • Case Time Limit: 10000MS
    • Time Limit: 10000MS
    • Judger: Normal

    Description

    You are given N relations about two words. Here relation means the two words can change from each other. Then I have m times queries about whether given two strings are the same. Every string has no more than 100 words. Every word has no more than 10 letters. To make two strings same, you can exchange the position of any two words in the string.

    Input

    The number of the relations N (1<=N<=10000), and what they are.

    The number of the test case M (1<=M<=10000) , and what they are. Please read sample for more.

    Output

    For each case out put “yes” if the two string may be same, otherwise, output “no”. You should also output “Case + one space + No. + : + one space” before the answer.

    For more details, please read the sample.

    Sample Input

    3
    i wo
    love ai
    you ni
    5
    ni
    wo
    i love you
    wo ai ni
    i love you
    ni ai wo ma
    i love you
    ni ai wo
    i love you
    ni wo
    

    Sample Output

    Case 1: no
    Case 2: yes
    Case 3: no
    Case 4: yes
    Case 5: no
    #include <iostream>
    #include <map>
    #include <string>
    #include <stdio.h>
    #include <algorithm>
    using namespace std;
    const int N = 10005;
    int array[N];
    int buffer[N];
    int root[N];
    int findroot( int );
    int main()
    {
        int n, i, j, m, p, q, num = 0;
        string temp1, temp2;
        map<string, int> magic;
        while( scanf( "%d", &n ) != EOF )
        {
            // 我的爸爸就是我^^
            for( i=1; i<=n; ++i )
                root[i] = i;
     
            for( i=1; i<=n; ++i )
            {
                cin >> temp1;
                if( magic[temp1] == 0 )
                    magic[temp1] = i;
                cin >> temp2;
                if( magic[temp2] == 0 )
                    magic[temp2] = i;
                p = findroot(magic[temp1]);
                q = findroot(magic[temp2]);
                if( p != q )
                    root[p] = q;
            }
            scanf( "%d", &m );
            for( i=1; i<=m; ++i )
            {
                p = q = 0;
                while( cin >> temp1 )
                {
                    array[p++] = root[magic[temp1]];
                    if( getchar() == '
    ' )
                        break;
                }
                while( cin >> temp1 )
                {
                    buffer[q++] = root[magic[temp1]];
                    if( getchar() == '
    ' )
                        break;
                }
     
                if( p != q )
                    cout << "Case " << ++num << ": no" << endl;
                else
                {
                    sort( array, array+p );
                    sort( buffer, buffer+q );
                    for( j=0; j<p; ++j )
                        if( array[j] != buffer[j] )
                            break;
     
                    if( j == p )
                        cout << "Case " << ++num << ": yes" << endl;
                    else
                        cout << "Case " << ++num << ": no" << endl;
                }
            }
        }
        return 0;
    }
    int findroot( int i )
    {
        int n = i;
        while( root[n] != n )
            n = root[n];
        int t = i;
        int temp;
        while( root[t] != t )
        {
            temp = root[t];
            root[t] = n;
            t = temp;
        }
        return n;
    }
  • 相关阅读:
    Java FileInputStream与FileReader的区别
    java 保存和读取本地json文件
    java写文件时往末尾追加文件(而不是覆盖原文件),的两种方法总结
    Java魔法堂:注解用法详解——@SuppressWarnings
    使用Restlet Client发送各种Get和Post请求
    postman VS restlet client基本使用
    Java获取请求客户端的真实IP地址
    dom4j解析xml字符串实例
    C++ Boost库简介(一些自己的感受)
    打仗其实最讲成本核算,大炮轰的都是黄金,日军在中国就是不断赔本
  • 原文地址:https://www.cnblogs.com/zhongshuxin/p/3276773.html
Copyright © 2020-2023  润新知