zoukankan      html  css  js  c++  java
  • Problem D: More is better

    Description

    Mr Wang wants some boys to help him with a project. Because the project is rather complex, the more boys come, the better it will be. Of course there are certain requirements.Mr Wang selected a room big enough to hold the boys. The boy who are not been chosen has to leave the room immediately. There are 10000000 boys in the room numbered from 1 to 10000000 at the very beginning. After Mr Wang's selection any two of them who are still in this room should be friends (direct or indirect), or there is only one boy left. Given all the direct friend-pairs, you should decide the best way.

    Input

    The first line of the input contains an integer n (0 ≤ n ≤ 100 000) - the number of direct friend-pairs. The following n lines each contains a pair of numbers A and B separated by a single space that suggests A and B are direct friends. (A ≠ B, 1 ≤ A, B ≤ 10000000)

    Output

    The output in one line contains exactly one integer equals to the maximum number of boys Mr Wang may keep.

    Sample Input

    3
    1 3
    1 5
    2 5
    4
    3 2
    3 4
    1 6
    2 6
    
    

    Sample Output

    4
    5

     题目链接:More is better

    二刷代码:

    #include <bits/stdc++.h>
    using namespace std;
    const int MAX=1e5+2;
    int cnt[MAX], father[MAX];
    int findFather(int x){
        if(x != father[x]) father[x] = findFather(father[x]);
        return father[x];
    }
    int main(){
        int i, n, u, v, ans;
        while(cin >> n){
            for(i=0; i<MAX; i++){
                cnt[i] = 1;
                father[i] = i;
            }
            ans = 1;
            for(i=0; i<n; i++){
                scanf("%d %d", &u, &v);
                u = findFather(u);
                v = findFather(v);
                if(u != v){
                    cnt[u] += cnt[v];
                    ans = max(ans, cnt[u]);
                    father[v] = u;
                }
            }
            printf("%d
    ", ans);
        }
        return 0;
    }

    总结:比第一次写的代码简洁为了一些,代码的逻辑也更加清晰了。

    最终AC代码:

    #include <bits/stdc++.h>
    using namespace std;
    const int MAX=1e7+2; 
    int father[MAX], cnt[MAX];
    int findFather(int x){ //这段代码值得细细品味 
        if(x == father[x]) return x;
        else{
            int temp = findFather(father[x]);
            father[x] = temp;
            return temp;
        }
    }
    int main(){
        int i, n, u, v, num, ans;
        while(cin >> n){
            if (n == 0){
                cout << 1 << endl;
                continue;
            }
            for(i=1; i<MAX; i++){
                cnt[i] = 1;
                father[i] = i;
            }
            ans = 1;
            for(i=0; i<n; i++){
                scanf("%d %d", &u, &v); //这里如果写成 cin > > u >> v;的话会超时! 
                u = findFather(u);
                v = findFather(v);
                if(u != v){
                    father[v] = u;
                    cnt[u] += cnt[v];
                }
                ans = max(ans, cnt[u]);
            }
            printf("%d
    ", ans);
        }
        return 0;
    }

    总结:之前了解cin的输入速度比scanf慢,但是在写这题时却忘了,然后线上OJ一直提示超时。(以后记得输入数据量很多时,别用cin、cout!!!结果截图如下:)

     然后,是解题思路的问题,我最开始写的代码如下:

    #include <bits/stdc++.h>
    using namespace std;
    const int MAX=1e7+2; 
    int father[MAX], cnt[MAX];
    int findFather(int x){
        if(x == father[x]) return x;
        else return father[x];
    }
    int main(){
        int i, n, u, v, num, index;
        while(cin >> n){
            for(i=1; i<MAX; i++){
                cnt[i] = 0;
                father[i] = i;
            }
            num = 0;
            for(i=0; i<n; i++){
                cin >> u >> v;
                num = max(num, max(u, v));
                u = findFather(u);
                v = findFather(v);
                if(u != v) father[v] = u;
            }
            for(i=1; i<=num; i++) cnt[father[i]]++;
            for(i=1; i<=num; i++){
                if(i != father[i]) cnt[father[i]] += cnt[i];
            }
            index = 0;
            for(i=1; i<=num; i++) if(cnt[index] < cnt[i]) index = i;
            printf("%d
    ", cnt[index]);
        }
        return 0;
    }

    过了测试用例,但是线上OJ提示:

    后来想了想,一个很大的问题是,输入的数据是无序的,然后每个i对应的father[i]在之后可能会被改变,而原先以i为根节点的变量却还是记录着i,而不是新的father[i]。并且,在后续统计个数时,也是比较繁琐的~之后就卡在这,一直没有解决。此外,对于输入为0时的情况也没有考虑到!

    再分析AC代码,可以发现更简洁,并且时间开销更少(毕竟少了三个for的遍历!)。简化解题步骤的过程在于思考问题的转变,将统计次数的任务在每次判别并查集的过程进行,一旦进行两个不同并查集的合并,就更新并记录最大值。于是,在输入数据结束后,也得到了答案。

    最后,想强调并查集的压缩路径的代码:

    int findFather(int x){ //这段代码值得细细品味 
        if(x == father[x]) return x;
        else{
            int temp = findFather(father[x]);
            father[x] = temp;
            return temp;
        }
    }

    嗯,这段代码是真的精巧~并且,比起用while循环的那种方式,我更喜欢这种精炼的形式,不仅更不易出错,而且即使是大数据集情况下时间开销也相近。至于为什么这段代码压缩了路径,我的理解是:在找到根节点后,返回时将根节点一同返回给了上层,于是将这条路径上的所有节点都直接指向了根节点,从而达到了压缩搜索路径的目的~在理解了上面的基础上,其实还有更简洁的写法,如下:

    int findFather(int x){ //更简洁的写法 
        if(x != father[x]) father[x] = findFather(father[x]);
        return father[x];
    }
  • 相关阅读:
    yii2.0 邮件发送如何配置
    php(ThinkPHP)实现微信小程序的登录过程
    微信小程序开发
    一个中高级PHP工程师所应该具备的能力
    如何解决PHP的高并发和大流量的问题
    对于PHP面试知识点的小结
    Centos7 redis设置开机自启动
    CENTOS7下REDIS设置密码、开放远程访问权限
    CentOS7安装Redis
    SQL Server 2012允许远程连接(Windows Server 2016)
  • 原文地址:https://www.cnblogs.com/heyour/p/12708470.html
Copyright © 2011-2022 走看看