zoukankan      html  css  js  c++  java
  • hiho 171周

    题目链接

    题目描述:

    输入
    4 alice 2 alice@hihocoder.com alice@gmail.com bob 1 bob@qq.com alicebest 2 alice@gmail.com alice@qq.com alice2016 1 alice@qq.com
    输出
    alice alicebest alice2016 bob

    如上所示,每一行前面是用户名,后面是他的邮箱,如果两个人共用了一个邮箱说明他是同一组的。

    输出分组后的结果。一组占一行。组间顺序和组内顺序保证和输入相同。

    数据大小是:最多10000个人,每个人最多10个email

    The first line contains an integer N, denoting the number of usernames. (1 < N ≤ 10000)

    Each username may have 10 emails at most.

    -----------------------------------------------------------------------------------------------------------------------------------------

    看着简单,还有有些细节需要注意的,比如顺序的保证。

    上来就想建图求联通分量,想了一下没必要:如果每组都有10个email,则需要建边10*9*1w=90w条边,太麻烦了

    后来一想用并查集做既省空间又省时间,每组的email都merge到每组的第一个上。这样每组的第一个email的父亲就对应着一个分组。

    #include <map>
    #include <cmath>
    #include <vector>
    #include <string>
    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    const int N = 10000*10 + 2;
    
    int father[N];
    int find(int id){
        int fid = father[id];
        if(fid==id) return fid;
        return father[id]=find(fid);
    }
    void merge(int a,int b){
        int fa = find(a);
        int fb = find(b);
        if(fa==fb) return;
        father[fb] = fa;
    }
    
    struct USER_MAILID{
        char name[256];
        int mailId;
    };
    USER_MAILID names[10100];
    
    vector<string > output_list[10100];
    map<int,int> father_ouputId;
    
    int main(){
        for(int i=0;i<N;i++) father[i]=i;
    
        map<string,int> mail_id_mapper;  int mailId = 0;
    
        int n,cnt; cin>>n;
        char strbuf[256]; int id_buf[16];
        for(int id=0;id<n;id++){
            scanf("%s%d",names[id].name,&cnt);
            for(int i=0;i<cnt;i++){
               scanf("%s",strbuf);
               auto iter = mail_id_mapper.find(strbuf);
               if(iter==mail_id_mapper.end()){
                  mail_id_mapper[strbuf] = (id_buf[i] = mailId++);
               }
               else{
                  id_buf[i] = iter->second;
               }
            }
            names[id].mailId = id_buf[0];
    
            for(int i=0;i<cnt;i++) for(int j=i+1;j<cnt;j++){
               merge(id_buf[i],id_buf[j]);
            }
        }
        int curId = 0; int outputId = 0;
        for(int id=0;id<n;id++){
            int f = find(names[id].mailId);
            auto iter = father_ouputId.find(f);
            if(iter==father_ouputId.end()){
                father_ouputId[f] = curId = outputId++;
            }
            else curId = iter->second;
            output_list[curId].push_back(names[id].name);
        }
        for(int i=0;i<outputId;i++){
            for(int j=0;j<output_list[i].size();j++){
                printf("%s ",output_list[i][j].c_str());
            }puts("");
        }
        return 0;
    }
  • 相关阅读:
    C
    A
    枚举子集的几种方法
    Codeforces Round #476 (Div. 2) [Thanks, Telegram!] ABCDE
    wannafly挑战赛14
    2018西安电子科大同步赛
    概率dp学习记录
    xcoj 1103 插线板(树链刨分求最大子段和)
    bzoj 2286(虚树+树形dp) 虚树模板
    bzoj3012(Trie)
  • 原文地址:https://www.cnblogs.com/redips-l/p/7660960.html
Copyright © 2011-2022 走看看