起先以为要我们找出的子图必须是完全图,敲了半天一看样例才知道只要找出连通子图就好。
</pre><pre name="code" class="cpp">#include<cstdio>
#include<cstring>
#include<string>
#include<vector>
#include<algorithm>
#include<iostream>
using namespace std;
const int N=2005;
string name[N];//从名字到节点序号的映射
int num;
int search(string s){
int i;
for(i=0;i<num;i++)
if(s==name[i])
return i;
name[num++]=s;
return num-1;
}
int map[N][N];
int thre;//阈值
void init(){
int i;
for(i=0;i<N;i++){
name[i]="";
memset(map[i],0,sizeof(map[i]));
}
num=0;
}
typedef struct message{
string name;
int valu;
message(){name=""; valu=0;}
}message;
bool comp(message a,message b){
return a.name<b.name;
}
vector<message> ans;
typedef struct fffunc{
bool visi[N];
message msg;
int whole,memb;
void oprt(int x){
//cout<<"x="<<x<<" "<<name[x]<<endl;
visi[x]=true;
memb++;
message temp;
temp.name=name[x];
int i;
for(i=0;i<num;i++)
if(map[x][i]>0){
temp.valu+=map[x][i];
if(!visi[i])
oprt(i);
}
whole+=temp.valu;
if(temp.valu>msg.valu){
msg.name=temp.name;
msg.valu=temp.valu;
}
}
void func(){
memset(visi,0,sizeof(visi));
int i;
for(i=0;i<num;i++)
if(!visi[i]){
//每次要遍历一个新的子图,whole保存子图中所有边的权重之和,memb保存子图中节点数
//msg用来保存子图中权值最大的那个点的姓名和权值
whole=0;
memb=0;
msg.name="";
msg.valu=0;
oprt(i);
whole/=2;//我在oprt函数中会把每个点的每条边都计算一次,这样每条边都被计算了两次,所以最后要除以2
if(whole>thre&&memb>2){
msg.valu=memb;
ans.push_back(msg);
}
}
}
}fffunc;
int main(){
init();
int m;
string sa,sb;
int a,b,c;
cin>>m>>thre;
while(m--){
cin>>sa>>sb>>c;
a=search(sa);
b=search(sb);
map[a][b]+=c;
map[b][a]+=c;
}
ans.clear();
fffunc f;
f.func();
int i;
printf("%d\n",ans.size());
sort(ans.begin(),ans.end(),comp);
for(i=0;i<ans.size();i++)
cout<<ans[i].name<<" "<<ans[i].valu<<endl;
return 0;
}