#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;
}
arena 2035
最新推荐文章于 2025-05-07 18:07:25 发布