PAT (Advanced Level) Practice A1034 Head of a Gang (30 分)(甲级)(C++)(图、BFS,map)

原题链接:A1034 Head of a Gang

#include<algorithm>
#include<iostream>
#include<cstdio>
#include<cstring>
#include <ctime>
#include <cmath>
#include <vector>
#include <set>
#include <map>
#include <stack>
#include <queue>
using namespace std;

typedef struct Record
{
    int time;//与其他人通话的时间
    int num;//该帮派中的总人数
    int total;//该帮派中所有人的通话总时间
    string name;//头目姓名
}Record;

const int MAX = 2010;//至多有1000条记录,所以涉及的人数共有两千人,否则会出现段错误
int Graph[MAX][MAX] = {0};//图的邻接矩阵表示,其数据表示两者的通话时间
Record Head[MAX] = {0};//存贮每个帮派的头目信息
int cnt = 0;
bool e_visited[MAX][MAX] = {0};//每条边是否被访问
bool v_visited[MAX] = {0};//每个顶点是否被访问
int N, K;

int id = 0;
map<string, int> name2id;
map<int, string> id2name;
int nameToID(string name)//把名字转为id号,并将对应的信息保存在map里
{
    map<string, int>::iterator it = name2id.find(name);
    if(it != name2id.end()) return it->second;
    id2name[id] = name;
    name2id[name] = id++;//id相当于一个计数器 
    return name2id[name];
}

void BFS(int v)//广度优先搜索
{
    int time = 0;
    queue<int> Q;
    Q.push(v);
    v_visited[v] = true;
    while(!Q.empty())
    {
        time = 0;//该人与其他人的通话时间
        v = Q.front();
        Q.pop();
        Head[cnt].num++;//该帮派中的总人数
        for(int i=0; i<id; i++)
        {
            time += Graph[v][i];
            if(Graph[v][i] && !e_visited[v][i])//该边未被访问,则记录总时间
            {
                Head[cnt].total += Graph[v][i];
                e_visited[v][i] = true;
                e_visited[i][v] = true;//并置已访问标记
                if(!v_visited[i])//该顶点未访问则入队
                {
                    Q.push(i);
                    v_visited[i] = true;
                }
            }
        }
        if(time > Head[cnt].time)//更新头目
        {
            Head[cnt].name = id2name[v];
            Head[cnt].time = time;
        }
    }
}

bool cmp(Record A, Record B)//按帮派头目名字的字典序排序
{
    return A.name < B.name;
}

int main()
{
    int id1, id2, time;
    string name1, name2;
    scanf("%d %d", &N, &K);
    for(int i=0; i<N; i++)
    {
        getchar();
        cin>>name1>>name2>>time;
        id1 = nameToID(name1);
        id2 = nameToID(name2);
        Graph[id1][id2] += time;//按无向图存贮即可
        Graph[id2][id1] += time;
    }
    for(int i=0; i<id; i++)
    {
        if(!v_visited[i])//该顶点尚未访问,说明是图的一个连通分量
        {
            BFS(i);
            if(Head[cnt].num > 2 && Head[cnt].total > K) cnt++;//该连通分量中的总人数和通话总时间满足要求,则帮派数++
            else//否则数据清零
            {
                Head[cnt].total = 0;
                Head[cnt].time = 0;
                Head[cnt].num = 0;
            }
        }
    }
    printf("%d\n", cnt);
    sort(Head, Head+cnt, cmp);//按帮派头目名字的字典序排序
    for(int i=0; i<cnt; i++)
    {
        cout<<Head[i].name<<" "<<Head[i].num<<endl;
    }
    return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值