使用并查集解决head of gang
作者:互联网
1034 Head of a Gang (30 分)
#include<iostream>
#include<map>
#include<string>
#include<vector>
using namespace std;
const int maxn=2010; //设置最大值
int num=0;int n,k;
int weight[maxn]; //每个gang的通话次数
vector<int> v[maxn];
map<string,int> stringToInt;
map<int,string> intToString;
map<string,int> gang;
struct people{
int w;
int father;
}peo[2010];
//将人名转化为数字编号
int change(string s){
if(stringToInt.find(s)!=stringToInt.end()){
return stringToInt[s];
}
else{
stringToInt[s]=num;
intToString[num]=s;
peo[num].father=num;
return num++;
}
}
//寻找根节点
int findFather(int x){
int a=x;
while(x!=peo[x].father){
x=peo[x].father;
}
int max=x; //寻找连通分量中的最大结点
while(a!=peo[a].father){ //压缩路径
int z=a;
if(peo[z].w>peo[max].w){
max=z;
}
a=peo[x].father;
peo[z].father=x;
}
if(max!=x){ //最大结点不是根节点则交换
peo[max].father=max;
peo[x].father=max;
}
return max;
}
//合并结点
void Union(int a,int b){
int A=findFather(a);
int B=findFather(b);
if(A!=B){
if(peo[A].w<=peo[B].w)
peo[A].father=B;
else
peo[B].father=A;
}
}
//输入结点初始化
void init(){
int i;
string s1,s2;
int w;
for(i=1;i<=n;i++){
cin>>s1>>s2>>w;
int id1=change(s1);
int id2=change(s2);
peo[id1].w+=w;
peo[id2].w+=w;
v[id1].push_back(w); //用向量保存边权
Union(id1,id2);
}
}
//遍历
void travel(){
int i,id,w;
for(i=0;i<num;i++){
id=findFather(i);
if(!v[i].empty()){
for(int j=0;j<v[i].size();j++){
weight[id]+=v[i][j];
}
}
gang[intToString[id]]+=1;
}
map<string,int>::iterator it;
for(it=gang.begin();it!=gang.end();it++){
string s=it->first;
id=stringToInt[s];
if(weight[id]<=k){
gang.erase(it);
continue;
}
if(it->second<3){
gang.erase(it);
}
}
}
int main(){
cin>>n>>k;
init();
travel();
map<string,int>::iterator it;
cout<<gang.size()<<endl;
for(it=gang.begin();it!=gang.end();it++){
cout<<it->first<<" "<<it->second<<endl;
}
return 0;
}
标签:head,num,int,max,查集,father,peo,gang,stringToInt 来源: https://blog.csdn.net/yanjinin/article/details/101058005