描述
You are given a list of usernames and their email addresses in the following format:
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
Your task is to merge the usernames if they share common email address:
alice alicebest alice2016
bob
输入
The first line contains an integer N, denoting the number of usernames. (1 < N ≤ 10000)
The following N lines contain N usernames and their emails in the previous mentioned format.
Each username may have 10 emails at most.
输出
Output one merged group per line.
In each group output the usernames in the same order as the input.
Output the groups in the same order as their first usernames appear in the input.
样例输入
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
描述
You are given a list of usernames and their email addresses in the following format:
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
Your task is to merge the usernames if they share common email address:
alice alicebest alice2016
bob
输入
The first line contains an integer N, denoting the number of usernames. (1 < N ≤ 10000)
The following N lines contain N usernames and their emails in the previous mentioned format.
Each username may have 10 emails at most.
输出
Output one merged group per line.
In each group output the usernames in the same order as the input.
Output the groups in the same order as their first usernames appear in the input.
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
vector<int> group[10000];
int father[10010];
bool flag[10010] = {false};
void Union(int a, int b){
int ta = a, tb = b;
while(flag[a]) a = father[a];
while(flag[b]) b = father[b];
if(a == b) return;
if(a > b) {swap(a, b);swap(ta, tb);}
group[a].push_back(tb);
for(auto i = group[b].begin(); i!=group[b].end(); i++){
group[a].push_back(*i);
}
flag[tb] = true;
}
int main(){
int n;
cin>>n;
string name[10010];
map<string, int> mail;
for(int i = 0; i<n; i++){
int m;
cin>>name[i]>>m;
for(int j = 0; j<m; j++){
string temp; cin>>temp;
if(mail.count(temp) == 0){
mail[temp] = i;
}
else{
if(!flag[i]){
flag[i] = true;
int tt = mail[temp];
while(flag[tt]){
tt = father[tt];
}
father[i] = tt;
group[tt].push_back(i);
}
else{
Union(father[i], mail[temp]);
}
}
}
}
for(int i = 0; i<n; i++){
if(!flag[i]){
cout<<name[i];
sort(group[i].begin(), group[i].end());
for(auto j = group[i].begin(); j != group[i].end(); j++){
cout<<" "<<name[*j];
}
cout<<endl;
}
}
return 0;
}
代码很难看,并且显示TLE(只有30分),可能是按照依次找到邮箱的所有者并且merge这一块有问题,于是找了下网上的方法。
string name[10010];
map<string, vector<int>> mail;
int father[10010];
int findf(int a){
while(father[a] != a) a = father[a];
return a;
}
void Union(int a, int b){
int fa = findf(a); int fb = findf(b);
if(fa != fb){
if(fa < fb) father[fb] = fa;
else father[fa] = fb;
}
}
int main(){
int n;
cin>>n;
for(int i = 0; i<n; i++){
cin>>name[i];
father[i] = i;
int m; cin>>m;
for(int j = 0; j<m; j++){
string temp; cin>>temp;
mail[temp].push_back(i);
}
}
for(auto i = mail.begin(); i != mail.end(); i++){
int len = (int)i->second.size();
for(int j = 1; j<len; j++){
Union(i->second[0], i->second[j]);
}
}
vector<int> group[10010];
for(int i = 0; i<n; i++){
if(findf(i) != i) group[findf(i)].push_back(i);
}
for(int i = 0; i<n; i++){
if(findf(i) == i){
cout<<name[i];
for(int j = 0; j<group[i].size(); j++){
cout<<" "<<name[group[i][j]];
}
cout<<endl;
}
}
}