PAT (Advanced Level) 1034 Head of a Gang (带权并查集+离散化)

版权声明:本文为博主原创文章,未经博主允许不得转载。 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;
}

猜你喜欢

转载自blog.csdn.net/w419387229/article/details/81987454