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
题意解析:
给出n段通话记录,每段通话记录包括 成员1name 成员2name 通话时长 三个数据。对某个互相连通的通话簇内,若人数>2,且总通话时长>给定时限,则认定其为一个黑帮组织,其头目为簇内通话时长最长的人。
要求输出黑帮数,以及每个黑帮的头目和帮内成员数(按照黑帮头目名字的字典序从小到大输出。)
解题分析:
由于要求按照黑帮头目名字字典序从小到大输出,考虑将黑帮存储为map<string,int> bang;内,前者为头目姓名,后者为帮内组员。
设置两个字典,分别实现名称到编号,编号到名称的映射,通过dfs搜索遍历实现。
代码如下:
#include<iostream>
#include<string>
#include<map>
using namespace std;
int G[2033][2033]={0},n,k,num=0,weight[2033];//weight[]存储各个用户的通话量
bool visit[2033]={false};
map<string,int> sti; //名字到编号的映射
map<string,int> gang; //黑帮
map<int,string> its; //编号到名称
int change(string str){ //实现将名称转换为编号,方便后续运算。
if(sti.find(str)!=sti.end()){ //若此名称已有编号则输出其编号。
return sti[str];
}
else{ //无编号,则设定编号,分别存入两个map中,实现后期转换。
sti[str]=num;
its[num]=str;
return num++;
}
}
void dfs(int x,int &head,int &member,int &total){ //x为当前遍历用户,head为当前头目编号,menber为成员数,total为该簇总的通话时长。
member++;
visit[x]=1;
if(weight[x]>weight[head]) head=x;
for(int i=0;i<num;i++){
if(G[x][i]>0){
total+=G[x][i];
G[x][i]=G[i][x]=0;
if(!visit[i]) dfs(i,head,member,total);
}
}
}
void dfstravel(){ //对所有用户进行遍历搜索。
for(int i=0;i<num;i++){
if(!visit[i]){
int head=i,member=0,total=0; //选第一个用户为头目,头目在后期遍历中会动态更改。
dfs(i,head,member,total);
if(total>k && member>2) gang[its[head]]=member;
}
}
}
int main(){
int w;
string str1,str2;
cin>>n>>k;
for(int i=0;i<n;i++){
cin>>str1>>str2>>w;
int id1=change(str1);
int id2=change(str2);
weight[id1]+=w;
weight[id2]+=w;
G[id1][id2]+=w; //此处,由于相同两个人可能多次通话,因此不能直接设值,需要累加。
G[id2][id1]+=w;
}
dfstravel();
cout<<gang.size()<<endl;
for(map<string,int>::iterator it=gang.begin();it!=gang.end();it++){
cout<<it->first<<" "<<it->second<<endl;
}
return 0;
}