【PAT】1034 Head of a Gang (30) [graph][dfs]

本文详细解析了牛客网1034题Head of a Gang的算法实现过程,探讨了图论中的深度优先搜索(DFS)算法在解决团伙识别问题中的应用。文章通过代码示例展示了如何使用C++进行图的构建、节点权重计算及团伙成员识别,并针对特定测试点进行了错误分析和修正。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1034 Head of a Gang (30分)
牛客 1034 Head of a Gang (30分)

  • 测试点3对gang排序后正确

  • 其他测试点…快被整疯了,牛客上可以过PAT过不了

  • 测试点1和2应该是输出0,其他的应该是输出格式问题?
    在这里插入图片描述
    (后来发现了,我设定输入的名字出现了bug,我只考虑了名字格式为AAA情况,牛客上的测试用例也只有“AAA”或者是“A”,如果名字是ABC就会出错)

  • map.count(Key)返回值为1或者0,1返回存在,0返回不存在,返回的是布尔类型的值,因为在map类型中所有的数据的Key值都是不同的,所以被count的数要么存在1次,要么不存在

AC版 (加了nameToi名字转序号)
在这里插入图片描述

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<algorithm>
#include<string>
#include<vector>
#include<map>
using namespace std;

int arc, thre;
int order;//结点编号
int gang,sumWeight;
bool graph[2000][2000];//图
int weight[2000];//权值
bool visited[2000];
vector<int> groupTemp;
map<string,int> group;
map<int,string> name;

void dfs(int node)
{
	if (weight[gang] < weight[node])
		gang  = node;

	visited[node] = true;
	sumWeight += weight[node];

	for (int i = 0; i < (int)name.size(); i++)
		if (!visited[i]  && graph[node][i])
		{
			groupTemp.push_back(i);//加入团伙
			dfs(i);
		}
}

int nameToi(string s)//名字转序号
{
	int flag = 0;
	for (auto it = name.begin(); it != name.end(); it++)
		if (s == it->second)
			return it->first;//如果已有直接返回序号

	//如果名字不存在
	name.insert(pair< int, string>(order, s));//插入姓名map,键值是name的字母序号 ,关键字是name
	//例如:name[0] = 'A',name[2]='C'
	return order++;
}

int main()
{
	freopen("input.txt", "r", stdin);
	scanf("%d%d", &arc, &thre);

	fill(graph[0], graph[0]+1000*1000, false);
	fill(weight, weight + 1000, 0);
	fill(visited, visited + 1000 , false);

	for (int i = 0; i < arc; i++)
	{
		int time;
		string sa, sb;
		cin >> sa >>sb >> time;

		int a = nameToi(sa);
		int b = nameToi(sb);//字母转数字序号

		graph[a][b] = 1;
		graph[b][a] = 1;

		weight[a] += time;
		weight[b] += time;
	}
	int cnt = 0;
	for (int i = 0; i < (int)name.size() ; i++)//遍历所有结点
	{
		if (!visited[i] )
		{
			groupTemp.clear();
			gang = -1;
			sumWeight = 0;
			dfs(i);
			if (sumWeight/2 > thre && groupTemp.size() > 1)
			{
				group.insert(pair< string,int>(name[gang], groupTemp.size() + 1));
				cnt++;//dfs次数+1
			}
		}
	}
	cout << cnt <<endl;
	for (auto it = group.begin(); it != group.end(); it++)
		cout << it->first<<" "<< it->second << endl;
	return 0;
}

部分正确版 (没有考虑名字为ABC情况)

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<string>
#include<vector>
#include<map>
#include<algorithm>
using namespace std;

int arc, thre;
int maxTime,gang,people,sumWeight;
bool graph[2000][2000];//图
int weight[2000];//权值
bool visited[2000];
vector<int> groupTemp;
map<string,int> group;
map<int,string> name;

void dfs(int node)
{
	if (weight[gang] < weight[node])
		gang  = node;

	visited[node] = true;
	sumWeight += weight[node];

	for (int i = 0; i < 26; i++)//这里是26,因为name是用首字母位置记录的
		if (!visited[i] && weight[i]!=0 && graph[node][i])
		{
			groupTemp.push_back(i);//加入团伙
			dfs(i);
		}
}

int main()
{
	freopen("input.txt", "r", stdin);
	scanf("%d%d", &arc, &thre);

	fill(graph[0], graph[0]+1000*1000, false);
	fill(weight, weight + 1000, 0);
	fill(visited, visited + 1000 , false);

	for (int i = 0; i < arc; i++)
	{
		int time;
		string sa, sb;
		cin >> sa >>sb >> time;

		int a = (int)sa[0] - 'A';
		int b = (int)sb[0] - 'A';//字母转数字序号

		name.insert(pair<int, string>(a, sa));//插入姓名map,键值是name的字母序号 ,关键字是name
		name.insert(pair<int, string>(b, sb));//例如:name[0] = 'A',name[2]='C'

		graph[a][b] = 1;
		graph[b][a] = 1;

		weight[a] += time;
		weight[b] += time;
	}
	int cnt = 0;
	for (int i = 0; i < (int)name.size() ; i++)//遍历所有结点
	{
		if (!visited[i] &&weight[i]!=0)//weight[i]!=0过滤实际不存在的结点
		{
			groupTemp.clear();
			gang = -1;
			sumWeight = 0;
			dfs(i);
			if (sumWeight/2 > thre && groupTemp.size() > 1)
			{
				group.insert(pair< string,int>(name[gang], groupTemp.size() + 1));
				cnt++;//dfs次数+1
			}
		}
	}
	cout << cnt <<endl;
	for (auto it = group.begin(); it != group.end(); it++)
		cout << it->first<<" "<< it->second << endl;
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值