PAT甲级1034

1034. Head of a Gang (30)

时间限制
100 ms
内存限制
65536 kB
代码长度限制
16000 B
判题程序
Standard
作者
CHEN, Yue

One way that the police finds the head of a gang is to check people's phone calls. If there is a phone call between A and B, we say that A and B is related. The weight of a relation is defined to be the total time length of all the phone calls made between the two persons. A "Gang" is a cluster of more than 2 persons who are related to each other with total relation weight being greater than a given threshold K. In each gang, the one with maximum total weight is the head. Now given a list of phone calls, you are supposed to find the gangs and the heads.

Input Specification:

Each input file contains one test case. For each case, the first line contains two positive numbers N and K (both less than or equal to 1000), the number of phone calls and the weight threthold, respectively. Then N lines follow, each in the following format:

Name1 Name2 Time

where Name1 and Name2 are the names of people at the two ends of the call, and Time is the length of the call. A name is a string of three capital letters chosen from A-Z. A time length is a positive integer which is no more than 1000 minutes.

Output Specification:

For each test case, first print in a line the total number of gangs. Then for each gang, print in a line the name of the head and the total number of the members. It is guaranteed that the head is unique for each gang. The output must be sorted according to the alphabetical order of the names of the heads.

Sample Input 1:
8 59
AAA BBB 10
BBB AAA 20
AAA CCC 40
DDD EEE 5
EEE DDD 70
FFF GGG 30
GGG HHH 20
HHH FFF 10
Sample Output 1:
2
AAA 3
GGG 3
Sample Input 2:
8 70
AAA BBB 10
BBB AAA 20
AAA CCC 40
DDD EEE 5
EEE DDD 70
FFF GGG 30
GGG HHH 20
HHH FFF 10
Sample Output 2:
0

/*
#include<iostream>
#include<cstdio>
#include<vector>
#include<string>
#include<set>
#include<algorithm>
using namespace std;
const int maxn = 26 * 26 * 26;
set<int> V;
int String2Int(string s)
{
	int sum = 0;
	for (int i = 0; i < 3; i++)
	{
		sum += (s[2-i] - 'A')*pow(26, i);
	}
	return sum;
}
string Int2String(int hash)
{
	string s = "AAA";
	for (int i = 0; i < 3; i++)
	{
		s[2-i] += hash % 26;
		hash /= 26;
	}
	return s;
}
int G[maxn][maxn] = { 0 };
bool vis[maxn] = { false };
int gangmembers = 0;
int personaltotalweight[maxn] = { 0 };
int totalweight = 0;
int maxtotalweight = 0;
int head_gangmembers[maxn] = { 0 };
int head;
int N, K;
vector<int> heads;
void DFS(int u)
{
	vis[u] = true; gangmembers++;
	if (maxtotalweight <= personaltotalweight[u])
	{
		maxtotalweight = personaltotalweight[u];
		head = u;
	}
	for (set<int>::iterator it = V.begin();
		it!=V.end();it++)
	{
		if (G[u][*it]>0)//这里一定要注意无向图的特性,若存储还是按有向图存储,
		//那么对无向图遍历时则注意使相邻点只满足弱连通即可
		{
			totalweight += G[u][*it];
			G[u][*it] = G[*it][u] = 0;//防止回头
			if(!vis[*it])
			DFS(*it);
		}
		//personaltotalweight[u] += G[u][*it] + G[*it][u];//统计时也要注意是否能放在if语句内
	}
}
void DFSTrave()
{
	for (set<int>::iterator it = V.begin();
		it != V.end(); it++)
	{
		gangmembers = 0;
		totalweight = 0;
		maxtotalweight = 0;//这样的重置条件不能轻易放在if语句中
		if (!vis[*it])
		{
			DFS(*it);
			if (gangmembers > 2 && totalweight > K)
			{
				heads.push_back(head);
				head_gangmembers[head] = gangmembers;
			}
		}
	}
}
int main()
{
	scanf("%d %d", &N, &K);
	string s1, s2; int weight;
	for (int i = 0; i < N; i++)
	{
		cin >> s1 >> s2 >> weight;
		int i1 = String2Int(s1);
		int i2 = String2Int(s2);
		G[i1][i2] += weight;//注意两个相同的人可能不止是一次AAA BBB 10,下一个还可能是AAA BBB 20
		G[i2][i1] += weight;
		personaltotalweight[i1] += weight;
		personaltotalweight[i2] += weight;
		V.insert(i1);
		V.insert(i2);
	}
	DFSTrave();
	cout << heads.size()<<endl;
	for (int i = 0; i < heads.size(); i++)
	{
		cout << Int2String(heads[i]) << " "
			<< head_gangmembers[heads[i]] << endl;
	}
	return 0;
}
*/
/*这题不知道为什么,调了一晚上还调不好,就剩2号测试点过不了。最开始自己写就是2号过不了
然后对照别人AC的代码改还是AC不了,不知道为啥。可能我用set的缘故,因为其他人都没用set
但我自己又感觉问题应该不是出现在set上。唉,DEBUG折寿啊,脑壳痛╭(╯^╰)╮。下面贴上别人
ac的代码*/
#include<iostream>
#include<string>
#include<map>
#include<vector>
using namespace std;

const int M = 26 * 26 * 26;	//结点最大数目
vector<int> v[M];	//图的邻接表表示
vector<int> node;	//存储遍历的起点
int visited[M] = { 0 };
int w[M] = { 0 };	//存储每个人的通话时长
int n, k;	//k是阈值
int cnt = 0;//达标的帮派数目
int pnum;	//一个帮派的成员数
int maxtime;//成员中的最大通话时长
int headtime;//头目通话时长
int headId;//头目id

int toId(string &s);//字符串名字转换为数字编号
string toName(int x);//编号转换为名字,用于输出
void dfs(int start);//dfs算法

int main()
{
	//freopen("in.txt", "r", stdin);
	cin >> n >> k;

	for (int i = 0; i < n; i++)//读入数据,同时转换成数字编号
	{
		string s1, s2;
		int wgt;
		cin >> s1 >> s2 >> wgt;

		int d1 = toId(s1);
		int d2 = toId(s2);
		v[d1].push_back(d2);
		v[d2].push_back(d1);
		w[d1] += wgt;
		w[d2] += wgt;
		node.push_back(d1);//稀疏边,存储遍历的起点。这样不需要从0一个个遍历了
	}

	map<string, int> h_map;//利用map的有序性,存储头目信息
	vector<int>::iterator it;
	for (it = node.begin(); it < node.end(); it++)
	{
		pnum = 0;
		maxtime = 0;
		headtime = 0;
		if (visited[*it] == 0)
			dfs(*it);

		if (pnum > 2 && maxtime > 2 * k)//判断是否符合条件的帮派
		{
			cnt++;
			string name = toName(headId);
			h_map[name] = pnum;
		}
	}

	cout << cnt << endl;//输出
	if (cnt != 0)
	{
		map<string, int>::iterator it;
		for (it = h_map.begin(); it != h_map.end(); it++)
			cout << it->first << ' ' << it->second << endl;
	}

	return 0;
}

int toId(string &s)//字符串名字转换为数字编号
{
	return ((s[0] - 'A') * 26 * 26 + (s[1] - 'A') * 26 + (s[2] - 'A'));
}

string toName(int x)//编号转换为名字,用于输出
{
	string s(3, 0);
	s[2] = x % 26 + 'A';
	s[1] = x / 26 % 26 + 'A';
	s[0] = x / 26 / 26 + 'A';

	return s;
}

void dfs(int start)//dfs算法, 里面用到的变量为便于遍历,都设为全局变量
{
	visited[start] = 1;
	pnum++;
	maxtime += w[start];
	if (w[start] > headtime)//更新头目信息
	{
		headtime = w[start];
		headId = start;
	}

	for (unsigned i = 0; i < v[start].size(); i++)//dfs遍历邻接点
	{
		if (visited[v[start][i]] == 0)
			dfs(v[start][i]);
	}

	return;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
对于计算机专业的学生而言,参加各类比赛能够带来多方面的益处,具体包括但不限于以下几点: 技能提升: 参与比赛促使学生深入学习和掌握计算机领域的专业知识与技能,如编程语言、算法设计、软件工程、网络安全等。 比赛通常涉及实际问题的解决,有助于将理论知识应用于实践中,增强问题解决能力。 实践经验: 大多数比赛都要求参赛者设计并实现解决方案,这提供了宝贵的动手操作机会,有助于积累项目经验。 实践经验对于计算机专业的学生尤为重要,因为雇主往往更青睐有实际项目背景的候选人。 团队合作: 许多比赛鼓励团队协作,这有助于培养学生的团队精神、沟通技巧和领导能力。 团队合作还能促进学生之间的知识共享和思维碰撞,有助于形成更全面的解决方案。 职业发展: 获奖经历可以显著增强简历的吸引力,为求职或继续深造提供有力支持。 某些比赛可能直接与企业合作,提供实习、工作机会或奖学金,为学生的职业生涯打开更多门路。 网络拓展: 比赛是结识同行业人才的好机会,可以帮助学生建立行业联系,这对于未来的职业发展非常重要。 奖金与荣誉: 许多比赛提供奖金或奖品,这不仅能给予学生经济上的奖励,还能增强其成就感和自信心。 荣誉证书或奖状可以证明学生的成就,对个人品牌建设有积极作用。 创新与研究: 参加比赛可以激发学生的创新思维,推动科研项目的开展,有时甚至能促成学术论文的发表。 个人成长: 在准备和参加比赛的过程中,学生将面临压力与挑战,这有助于培养良好的心理素质和抗压能力。 自我挑战和克服困难的经历对个人成长有着深远的影响。 综上所述,参加计算机领域的比赛对于学生来说是一个全面发展的平台,不仅可以提升专业技能,还能增强团队协作、沟通、解决问题的能力,并为未来的职业生涯奠定坚实的基础。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值