一二三四五 上山打老虎

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;
}

posted @ 2021-03-01 20:24  黒川川  阅读(64)  评论(0)    收藏  举报