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

解题过程的小记录,如有错误欢迎指出。

难度:五星(很多变量很晕,不过也是我方法没选对的原因,可以跟着算法笔记的章节打一遍邻接图的)

题目分析

给出一堆通话记录,打过电话就说明在一个黑帮里,一通电话两个打的人都要加各自的通话时长,找出总共有几个大于门槛人数值的黑帮,以及输出他们的大佬(团队中通话时长最长的人)的名字和团队人数

注意点

  1. 最后输出的顺序要按照黑帮大佬的姓名的顺序

我的解题过程

思路

我是采用邻接表利用vector做的,具体见代码注释用

bug

  1. 团队总人数统计错误,不应该放在循环体内
  2. 输出的时候没有进行姓名排序

代码

#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的代码

全部代码因版权原因不放出来,大家可以自行去柳神博客购买或者参考晴神的上机笔记~

借鉴点

  1. 本题可以参考上机笔记对应篇章,最好自己打一遍,学习以下map映射的写法
  2. 也可以跟着柳神的代码打一遍自己添加注释
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值