题意:
给出N条通话记录,这些通话将他们分为若干组。每个组的总边权为该组内的所有通话的长度之和,每个人的点权设为该人参加的通话长度之和。给定阀值K,超过阀值且大于二人的组被视为犯罪团伙,而组内点权最大的人被视为头目,要求输出团伙个数和每个团伙的头目,以及成员个数。
思路:
- 首先是姓名字符串和编号的对应关系:map<string,int>
- 求某点相连的边权之和
- 进行图的遍历,获取每个连通块的头目、成员个数、总边权。
- 如果总边权>K,且人数>2,则记录为一个犯罪团伙
代码:
#include<iostream>
#include<map>
using namespace std;
map<string,int> stringToint;
map<int, string> intTostring;
map<string, int> ans;
int idNumber=1,k;
int stoifunc(string s){
if(stringToint[s]==0){
stringToint[s]=idNumber;
intTostring[idNumber]=s;
return idNumber++;
}else{
return stringToint[s];
}
}
int G[2010][2010],weight[2010];
bool vis[2010];
void dfs(int u,int &head,int &numMember,int &totalweight){
vis[u]=true;
numMember++;
if(weight[u]>weight[head]){
head=u;
}
for(int v=1;v<idNumber;v++){
if(G[u][v]>0){
totalweight+=G[u][v];
G[u][v]=G[v][u]=0;
if(vis[v]==false){
dfs(v,head,numMember,totalweight);
}
}
}
}
void dfsTrave(){
for(int i=1;i<idNumber;i++){
if(vis[i]==false){
int head=i,numMember=0,totalweight=0;
dfs(i,head,numMember,totalweight);
if(numMember>2&&totalweight>k){
ans[intTostring[head]]=numMember;
}
}
}
}
int main(){
int n,w;
cin >> n >> k;
string s1,s2;
for(int i=0;i<n;i++){
cin >> s1 >> s2 >> w;
int id1=stoifunc(s1);
int id2=stoifunc(s2);
weight[id1]+=w;
weight[id2]+=w;
G[id1][id2]+=w;
G[id2][id1]+=w;
}
dfsTrave();
cout << ans.size() << endl;
for(auto it=ans.begin();it!=ans.end();it++){
cout<< it->first << " " << it->second <<endl;
}
return 0;
}