#include<cstdio> #include<string> #include<map> using namespace std; const int maxn=2010;//总人数 const int INF=1000000000;//无穷大 map<int,string> intToString;//编号-姓名 map<string,int> stringToInt;//姓名->编号 map<string,int> Gang;///head->人数 int G[maxn][maxn]={0},weight[maxn]={0};//邻接矩阵,点权weight int n,k,numPerson=0;//边数,下限k,总人数numPerson bool vis[maxn]={false};//标记是否被访问 //DFS函数访问单个连通块,目的是获取成员个数,总边权,每个连通块的头目,即连通块内权最大的结点。 //nowVisit为当前访问的编号。head 为头目,numMember为成员个数、totalValue为连通块的总边权,均为引用。 void DFS(int nowlist,int &head,int numMember,int& totalValue){ numMember++;//成员人数增加1 vis[nowVisit]=true;//标记nowVisit为已经访问 if(weight[nowVisit]>weight[head]){ //当前范文结点的点权大于头目的点权则更新头目 head=nowlist; } for(int i=0;i<numPerson;i++){//枚举所有人 if(G[nowVisit][i]>0){//如果从nowVisit能到达i totalValue+=G[nowVisit][i];//连通块的总边权增加该边权 G[nowVisit][i]=G[i][nowVisit]=0;//删除这条边,防止回头 if(vis[i]==false){//如果i未被访问,则递归访问i DFS(i,head,numMember,totalValue); } } } } //DFSTrave函数遍历整个图,获取每个连通块的信息 void DFSTrave(){ for(int i=0;i<numPerson;i++){//枚举所有人 if(vis[i]==false){//如果i未被访问 int head=i,numMember=0,totalValue=0;//头目,成员数、总边权 DFS(i,head,numMember,totalValue);//遍历i所在的连通块 //到这里就遍历结束了 if(numMember>2&&totalValue>k){//遍历结束后,成员数大于2且总边权大于k //head人数为numMember Gang[intToString[head]]=numMember;//以这个head为头目的帮派的总人数,注意这里用到了Map } } } } //change函数返回姓名str对应的编号 int change(string str){ if(stringToInt.find(str)!=stringToInt.end()){//如果str已经出现过 return stringToInt(str);//返回编号,不懂 } else{ stringToInt[str]=numPerson;//str对应的编号为numPerson intToString[numPerson]=str;//numPerson对应str return numPerson++;//总人数加1 } } 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);//将str1转化为编号Id1 int id2=change(str2);//将str2转化为编号id2 weight[id1]+=w; weight[id2]+=w; G[id1][id2]+=w; G[id2][id1]+=w; } DFSTrave();//遍历整个图的所有连通块,获取Gang的信息 cout<<Gang.size()<<endl;//Gang的个数 map<string,int>::iterator it; for(it=Gang.begin();it!=Gang.end();it++){//遍历所有的Gang cout<<it->first<<" "<<it->second<<endl;//输出信息 } return 0; }