PAT(A)1034Head of a Gang
题目链接:https://pintia.cn/problem-sets/994805342720868352/problems/994805456881434624
题意:给定一个n和一个k,然后给定n个a b num, a为长度为3的大写字母构成的字符串,b也是,num为a和b的通话时间,给定的图中强连通分量的权值和如果大于k且强连通分量中的顶点大于2则是一个gang,每个gang有一个head,head为点权和最大的点,保证每个gang有一个head,根据head的字典序排序输出head和顶点个数。
思路:DFS遍历图
第一步:建图,将字符串转换成整数类型,通过两个map<string,int> map<int,string> 建立关联,同时可以计算每个点的点权值。
第二步:对于每个未被访问的点进行dfs,对于每次dfs 会得到一个强连通分量,计算顶点个数和权值和,如果满足条件则找到head加入到一个map<string,int>来维护,map会自动根据string进行排序。
代码:
#include<bits/stdc++.h>
using namespace std;
int n,k;
map<string,int> si;
map<int,string> is;
int no=0;
struct node{
int b,v;
node(int _b,int _v):b(_b),v(_v){}
};
vector<struct node> edge[2005];
int allnum[2005]={0};
bool vis[2005]={false};
map<string,int>res;//结果
void dfs(int i,int &he,int &num,int &allv){//通过引用传参来实现返回多个值 重要
num++;
vis[i]=true;
if(allnum[i]>allnum[he])
he=i;
for(int j=0;j<edge[i].size();j++){
int ne=edge[i][j].b;
allv+=edge[i][j].v;//要先加上权值,避免漏算
if(!vis[ne]){
dfs(ne,he,num,allv);
}
}
}
void resolve(){
for(int i=0;i<no;i++){
int he=i,num=0,allv=0;
if(!vis[i]){
//cout<<i<<endl;
dfs(i,he,num,allv);
// cout<<num<<" "<<allv<<endl;
if(num>2&&allv>k){
res[is[he]]=num;
}
}
}
}
int main (){
cin>>n>>k;
string a,b;
int as,bs,num;
for(int i=0;i<n;i++){
cin>>a>>b>>num;
if(si.find(a)!=si.end()){
as=si[a];
}
else {
si[a]=no;
is[no]=a;
as=no;
no++;
}
if(si.find(b)!=si.end()){
bs=si[b];
}
else {
si[b]=no;
is[no]=b;
bs=no;
no++;
}
edge[as].push_back(node(bs,num));
allnum[as]+=num;//提前计算点权
allnum[bs]+=num;
}
resolve();
cout<<res.size()<<endl;
map<string,int>::iterator it; //迭代器使用
for(it=res.begin();it!=res.end();it++){
cout<<it->first<<" "<<it->second<<endl;
}
return 0;
}

浙公网安备 33010602011771号