版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/w419387229/article/details/81987454
这题感觉很不错,map、set、vector、pair的合理利用,对数据的妥善处理。值得好好记录下。
虽然题目本身思路比较简单,但是如果不能对数据进行好的处理,写起来还是相当麻烦的,我就是在倒腾了半天之后,感觉越写越乱,然后百度看到了一个很不错的方法,就学习了他的方法。原博链接
首先,要使用并查集我们必须要对name进行离散化,我竟然一开始想到的是用36进制转十进制。。。现在的方法,也是一种应该通用的方法,即利用map来映射name到一个数字上。然后用两个map就可以实现双向的映射关系,对于这题最后输出结果就很便利了。
随后,因为要进行union操作,而且这题的每个结点是带权的,所以用Node来记录每个结点的父亲和权值。之后的并查集部分就是常规的操作。
建立各个连通图后,需要对各个连通图进行信息的统计,并且需要记录有多少个连通图,因此这里又用到map,由于在union操作中,已经进行过路径压缩,因此所有的子结点都指向了一个父亲,所以可以将每个父亲作为key,value就是一个Gang的结构体,其中记录了各种所需的信息。这样信息的统计就比较简单了,循环遍历所有点,找到他们的父亲,在map里find他们的帮派是否存在并进行相应的操作。
最后就是统计所有满足条件的帮派,这里又有个小技巧,因为Gang里存的head是数字,因此那两个映射map就可以拿来找到相应的name,并且将各个head的name和帮派的member数make_pair,最后排序输出。
#include<iostream>
#include<cstdio>
#include<map>
#include<set>
#include<vector>
#include<cstring>
#include<algorithm>
using namespace std;
struct Call{
string a,b;
int time;
};
struct Node{
int time, father;
};
struct Gang{
int member = 0, time = 0, maxtime = -1, head = -1;
};
int n,k,cnt = 0;
map<string,int> name2id;
map<int,string> id2name;
set<string> name;
vector<Call> call;
Node dad[2005];
void init(){
for(int i = 0; i < 2005; ++i){
dad[i].father = i;
dad[i].time = 0;
}
}
int find(int x){
return dad[x].father == x ? x : dad[x].father = find(dad[x].father);
}
void merge(int x, int y){
int xx = find(x), yy = find(y);
dad[xx].father = yy;
}
int main(){
scanf("%d%d",&n,&k);
init();
//input
call.resize(n);
for(int i = 0; i < n; ++i){
cin >> call[i].a; cin >> call[i].b; cin >> call[i].time;
name.insert(call[i].a); name.insert(call[i].b);
}
//map name and id
set<string>::iterator it;
int id = 0;
for(it = name.begin(); it != name.end(); ++it, ++id){
name2id[*it] = id; id2name[id] = *it;
}
//union
int x, y, t;
for(int i = 0; i < call.size(); ++i){
x = name2id[call[i].a]; y = name2id[call[i].b]; t = call[i].time;
merge(x,y);
dad[x].time += t; dad[y].time += t;
}
//gang statistic
int len = name.size();
int tmpdad;
map<int,Gang> gangs;
map<int,Gang>::iterator gt;
for(int i = 0; i < len; ++i){
tmpdad = find(i);
gt = gangs.find(tmpdad);
if(gt != gangs.end()){//gangs exist, key = tmpdad
gangs[tmpdad].member++;
gangs[tmpdad].time += dad[i].time;
if(dad[i].time > gangs[tmpdad].maxtime){
gangs[tmpdad].head = i;
gangs[tmpdad].maxtime = dad[i].time;
}
}
else{//new gangs
Gang g;
g.member = 1;
g.time = dad[i].time;
g.maxtime = dad[i].time;
g.head = i;
gangs[tmpdad] = g;
}
}
//ans statistic
vector<Gang> ans;
for(gt = gangs.begin(); gt != gangs.end(); gt++){
if(gt->second.member > 2 && gt->second.time > k*2){
ans.push_back(gt->second);
}
}
vector< pair<string,int> > output;
for(int i = 0; i < ans.size(); ++i){
output.push_back(make_pair(id2name[ans[i].head],ans[i].member));
}
sort(output.begin(),output.end());
printf("%d\n",output.size());
for(int i = 0; i < output.size(); ++i){
cout << output[i].first << " " << output[i].second << endl;
}
return 0;
}