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;
}