题解 | #Head of a Gang#
Head of a Gang
https://www.nowcoder.com/practice/a31b1ea6c87647bc86e382acaf21c53b
//题目说人名是3个字母组成的,结果测试用例里面还有1、2个字母的人名
//这个题目思路很简单,就是磨人
#include <iostream>
using namespace std;
int sj[30];//在并查集的基础上,每个结点还要存通话时间
int height[30];
int father[30];
int visit[30];
int root[30];//记录哪些结点是根
int number[30];//每棵树的结点数量
long long total[30];//每棵树的总时长
string rm[30];//存各种长度的人名
int sl[30];//是否是首领
void Initial()
{
for(int i=0;i<30;i++)
{
height[i]=0;
father[i]=i;
sj[i]=0;
visit[i]=0;
root[i]=-1;//这里我i写成了30,就这个错误找了半小时,气死了
number[i]=0;
total[i]=0;
rm[i]="";
sl[i]=0;
}
}
int Find(int x)
{
if(father[x]==x)return x;
else
{
return Find(father[x]);
}
}
void Union(int a,int b)
{
a=Find(a);
b=Find(b);
if(a!=b)
{
if(height[a]>height[b])father[b]=a;
else if(height[a]<height[b])father[a]=b;
else
{
father[b]=a;
height[a]++;
}
}
}
int main() {
int a, b;
while (cin >> a >> b) {
Initial();
for(int i=1;i<=a;i++)
{
string str1,str2;int t;
cin>>str1>>str2>>t;
rm[str1[0]-'A']=str1;
rm[str2[0]-'A']=str2;
sj[str1[0]-'A']+=t;
sj[str2[0]-'A']+=t;
visit[str1[0]-'A']=1;
visit[str2[0]-'A']=1;
Union(str1[0]-'A',str2[0]-'A');
getchar();
}
//找出有哪些根
for(int i=0;i<30;i++)
{
if(visit[i])
{
if(i==Find(i))
{
root[i]=-2;
}
}
}
//找出每颗树的总时长和人数
for(int i=0;i<30;i++)
{
if(root[i]==-2)//i是根
{
for(int j=0;j<30;j++)
{
if(Find(j)==i)//是该树的结点
{
number[i]++;//该根对应的树的人数
total[i]+=(sj[j]);//该根对应的树的总通话时间*2
}
}
}
}
//找出是帮派的树 及其首领
int ans1=0;//帮派数量
int ans2;//首领字母对应的数字
for(int i=0;i<30;i++)
{
if(root[i]==-2)//i是根
{
if(number[i]>2&&total[i]>(b*2))//是帮派
{
ans1++;
//找该帮派的首领
for(int j=0;j<30;j++)
{
if(Find(j)==i)
{
ans2=j; //首领字母对应的数字
break;
}
}
for(int j=0;j<30;j++)
{
if(Find(j)==i)
{
if(sj[j]>sj[ans2])ans2=j;
}
}
root[i]=ans2;//root里存首领字母对应的数字
sl[ans2]=1;
}
}
}
cout<<ans1<<endl;
if(ans1!=0)
for(int i=0;i<30;i++)
{
if(sl[i]==1)
{
cout<<rm[i]<<" ";
cout<<number[Find(i)]<<endl;
}
}
}
}


查看4道真题和解析