解题过程的小记录,如有错误欢迎指出。
难度:五星(很多变量很晕,不过也是我方法没选对的原因,可以跟着算法笔记的章节打一遍邻接图的)
题目分析
给出一堆通话记录,打过电话就说明在一个黑帮里,一通电话两个打的人都要加各自的通话时长,找出总共有几个大于门槛人数值的黑帮,以及输出他们的大佬(团队中通话时长最长的人)的名字和团队人数
注意点
- 最后输出的顺序要按照黑帮大佬的姓名的顺序
我的解题过程
思路
我是采用邻接表利用vector做的,具体见代码注释用
bug
- 团队总人数统计错误,不应该放在循环体内
- 输出的时候没有进行姓名排序
代码
#include<iostream>
#include<vector>
#include<string>
#include<algorithm>
using namespace std;
const int MAXV = 26 * 26 * 26;
int n, k, total = 0, cnt = 0, people = 0, maxweight = 0, minname = 26 * 26 * 26 + 5;
bool vis[MAXV] = { false };
struct node {
int v, weight;
node(int _v, int _w) :v(_v), weight(_w) {}
};
vector<node> Node[MAXV], head;
int every[MAXV];
int toindex(char s[3]) {//将姓名转化为下标
int result = 0;
for (int i = 0; i < 3; i++) {
result = result * 26 + (s[i] - 'A');
}
return result;
}
void toname(int index) {//将下标变为姓名输出
string s = "";
int i = 0;
while (i++ < 3) {
s = (char)(index % 26 + 'A') + s;
index /= 26;
}
cout << s;
}
void DFS(int u, int depth) {
if (u >= MAXV) return;
people++;//******这里原来写错了,团伙人数只要遍历到就应该增加
vis[u] = true;//遍历过设置为true
int nowweight = every[u], nowname = u;//用于找出黑帮大佬
for (int i = 0; i < Node[u].size(); i++) {
int v = Node[u][i].v;
total += Node[u][i].weight;//总通话时长
if (vis[v] == false) DFS(v, depth + 1);//如果该黑帮中有通话过且没有遍历过的,则继续深入遍历
}
if (nowweight > maxweight) {
maxweight = nowweight;
minname = nowname;
}
else if (nowweight == maxweight) {
if (nowname < minname) minname = nowname;
}
}
int comp(node n1, node n2) {//用于比较黑帮头头的输出排序
return n1.v < n2.v;
}
void DFSTrace() {
for (int i = 0; i < MAXV; i++) {
total = 0;
people = 0;
maxweight = 0;
minname = 26 * 26 * 26 + 5;
if (vis[i] == false && Node[i].size() != 0) {
DFS(i, 1);
if (people > 2 && total > k) {//如果团伙人数大于2人,通话时长>门槛值,则算是一个团伙
cnt++;
head.push_back(node(minname, people));//推入团伙头集合中,不过这里团伙头的weight就是团伙人数了
}
}
}
}
int main()
{
scanf("%d %d", &n, &k);
for (int i = 0; i < n; i++) {
char s1[5], s2[5];
int w;
scanf("%s %s %d", s1, s2, &w);
int u = toindex(s1), v = toindex(s2);
every[u] += w;//存储每个人的通话时长,为了后边进行找出黑帮大佬的比较
every[v] += w;
Node[u].push_back(node(v, w));//推入u打出的电话的邻接表
}
DFSTrace();
cout << cnt << endl;//输出团伙个数
sort(head.begin(), head.end(), comp);
for (int i = 0; i < cnt; i++) {
toname(head[i].v);
printf(" %d\n", head[i].weight);
}
return 0;
}
dalao的代码
全部代码因版权原因不放出来,大家可以自行去柳神博客购买或者参考晴神的上机笔记~
借鉴点
- 本题可以参考上机笔记对应篇章,最好自己打一遍,学习以下map映射的写法
- 也可以跟着柳神的代码打一遍自己添加注释