九度 OJ1446 Head of a Gang PAT1034 並查集+map容器的使用

題目鏈接

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 threthold 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.
輸入描述:
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.
輸出描述:
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.
示例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
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
輸出
2
AAA 3
GGG 3
0

題目大意:
確定一個團隊隊長的方案是看隊員彼此之間的通話時間。如果一個團隊中,某個隊員和其他隊員的通話時間是最長的,那麼他就是隊長。有一些案例,輸入爲一些人之間的相互通話時間。找出每個案例中的團隊個數,團隊的限制應該是2個人以上(不包含2個人)並且隊員之間總的通話時間大於限制時間K,找出團隊的隊長和該團隊的成員個數。

解題思路:
1、由於每個人的ID是通過字符串給出的,因此需要離散化。注意輸出時要輸出隊長所對應的字符串,因此可以使用兩個map來進行字符串與編號之間的來回映射
2、使用並查集來尋找各個團隊;
3、按照要求對所有隊長的名字進行排序後輸出。

AC代碼:

#include<iostream>
#include<stdio.h>
#include<map>
#include<algorithm>
#include<string>
#include<string.h>
#include<vector>
#include<queue>
using namespace std;
#define maxn 2010
int weight[maxn];//每個人員的總通話時間
int tree[maxn];
map<string, int> Map;//使用兩個map來進行姓名與編號之間的來回映射
map<int, string> idx;
int cnt;//總的人員數量
void init() {
	for (int i = 0; i < maxn; i++) {
		weight[i] = 0;
		tree[i] = -1;
	}
	Map.clear();
	idx.clear();
	cnt = 0;//下一個可用的編號
}
int findroot(int a) {
	if (tree[a] == -1)return a;
	int tmp = findroot(tree[a]);
	tree[a] = tmp;
	return tmp;
}
void unit(int a, int b) {//合併根
	int fa = findroot(a);
	int fb = findroot(b);
	if (fa != fb) tree[fa] = fb;
}
struct gang {//團伙首領
	string name;
	int size;//團伙大小
	bool operator < (const gang &a) const {//按照首領姓名的字典序排列
		return name < a.name;
	}
};
int main() {
	int n, k;
	while (cin>>n>>k) {
		init();//初始化
		string a, b; int w;
		while (n--) {
			cin >> a >> b >> w;
			if (Map.find(a)==Map.end()) {//建立映射關係
				idx[cnt] = a;
				Map[a] = cnt++;
			}
			if (Map.find(b) == Map.end()) {
				idx[cnt] = b;
				Map[b] = cnt++;	
			}
			weight[Map[a]] += w;
			weight[Map[b]] += w;
			unit(Map[a], Map[b]);//並查集
		}
		vector<int> team;//保存團伙
		vector<gang> last;//保存團伙的首領
		for (int i = 0; i < cnt; i++) {
			if (tree[i] == -1) {
				team.push_back(i);
			}
		}
		for (int i = 0; i < team.size(); i++) {
			int no; int max_w = 0;//no是團伙首領的編號 max_w用於保存目前團伙成員中最大的權重
			int num = 0; int all = 0;//num是團伙中成員的數量 all是整個團伙的權重
			for (int j = 0; j < cnt; j++) {
				if (findroot(j) != team[i])continue;
				num++; all += weight[j];
				if (max_w < weight[j]) {
					max_w = weight[j]; no = j;
				}
			}
			if (num > 2 && all / 2 > k) {//滿足題目要求
				gang a; a.name = idx[no]; a.size = num;
				last.push_back(a);
			}
		}
		sort(last.begin(), last.end());//按照要求排序
		cout << last.size() << endl;
		for (int i = 0; i < last.size(); i++) {
			cout << last[i].name << " " << last[i].size << endl;
		}
	}
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章