PAT甲级 1034 Head of a Gang (30分)

1034 Head of a Gang (30分)

题目链接:PAT A 1034
在这里插入图片描述
在这里插入图片描述

题目大意:输入第一行给出两个数n和k,分别代表通话记录的条数以及阈值。随后n行给出两个人的通话记录。犯罪团伙被定义为多于两个人的通话时长加起来超过了阈值k,而犯罪团伙的头目被定义为团队中通话时间最长的那个人。题目要求找出每一个犯罪团伙的头目以及团队成员的个数。

思路分析:有难度的一道题。首先和我们之前做的图的题不太一样,图之间连接的节点是字母,而不是编号,这就需要我们将字母转换为数字,方便进行图的存储。首先定义三个map容器,分别是字符串转数字的map(用来记录名字对应的编号),数字转字符串的map(用来记录编号对应的名字),还有一个记录犯罪团伙的头目以及团队人数(这是因为题目中要求头目按照字母序从小到大输出,而map容器中的键正好是从小到大自动排序的,所以我们选择map容器来记录)。定义一个字符串转化函数,numperson变量用来记录总人数(输入的时候就已经确定),方便我们之后进行dfs遍历。之后在dfs函数中去统计每一个团队的人数和通话时长,需要注意的是,题中的图可能会有环,即一条边连接已访问节点的情况。但是我们仍然需要加上这条边的边权,而这样又可能导致一条边的边权被重复计算,所以每加完一条边的边权,就要将边权赋值为0(例如样例中的FFF,GGG,HHH就是这样的情况)。之后进行dfs遍历最后输出就可以了~

AC代码:

#include<iostream>
#include<map>
using namespace std;
map<string, int> stringtoint; //字符串转数字,记录名字对应的编号 
map<int, string> inttostring; //数字转字符串,记录编号对应的名字 
map<string, int> Gang; //记录头目和团伙个数 
int g[2010][2010] = {0}, numperson = 0, n, k, weight[2010] = {0}; //numperson记录总人数,weight数组记录每个人的通话时间 
bool vis[2010] = {false};
int change(string s) {
	if(stringtoint.find(s) != stringtoint.end()) //如果已经有这个名字了 
		return stringtoint[s]; //直接返回这个名字对应的编号 
	stringtoint[s] = numperson; 
	inttostring[numperson] = s;
	return numperson++; //先返回numperson的值,之后numperson在加一 
}
void dfs(int u, int &head, int &num, int &value) {
	vis[u] = true;
	num++; //团队人数加一 
	if(weight[u] > weight[head]) //更新头目 
		head = u;
	for(int i = 0; i < numperson; i++) {
		if(g[u][i] != 0) { //注意这里不能和下面vis[i]==false一起写 
			value += g[u][i]; //更新团队通话时间 
			g[u][i] = g[i][u] = 0; //防止重复计算边权 
			if(vis[i] == false) 
				dfs(i, head, num, value);
		}
	} 
}
void dfstravel() {
	for(int i = 0; i < numperson; i++) {
		if(vis[i] == false) {
			int head = i, num = 0, value = 0;
			dfs(i, head, num, value);
			if(num > 2 && value > k) 
				Gang[inttostring[head]] = num;
		}
	}
}
int main() {
	cin >> n >> k;
	int w, id1, id2;
	string str1, str2;
	for(int i = 0; i < n; i++) {
		cin >> str1 >> str2 >> w;
		id1 = change(str1);
		id2 = change(str2);
		weight[id1] += w;
		weight[id2] += w;
		g[id1][id2] += w;
		g[id2][id1] += w;
	}
	dfstravel();
	cout << Gang.size() << endl;
	for(auto it = Gang.begin(); it != Gang.end(); it++)
		cout << it->first << " " << it->second << endl; 
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值