pat1034Head of a Gang (30)

56 篇文章 0 订阅

题意分析:

(1)给出若干条通话记录(包括通话的两端的ID、时长),通过通话记录找出其中有多少个团伙,以及每个团伙的首领和团伙人数,所谓团伙就是指通过话的“联通”组织超过三人,可以理解为连通分量的人数超过三人,且集体通话时长超过一个给定的阈值。团伙首领是指在这个团伙中,这个人的通话时长最长

(2)此题的目标是寻找满足权值超过阈值、节点数超过2的联通分量,最简单的方法就是通过深度优先搜索遍历整个图;要寻找权值最大的节点,需要对每个节点维护其通话时长,由于一条通话的对端通话时长相等,因此最终的连通分量的权值是这些节点权值的一半。

(3)由于每个人的ID是通过字符串给出的,需要离散化。遍历的过程中需要实时更新权值最大的节点,使用map容器来完成对图的构建,以及使用map来对节点权值的索引;可以说此题就是在考察对map的灵活使用,当要遍历某个数据结构的时候,如果要检索的索引是字符串,就要考虑使用map,并且使用map来存储数据,天然已经按字符串的字典序排好了。最后输出的时候避免排序。

可能坑点:

(1)不要忘记最后所得连通分量的权值为所有节点权值的一半

#include <iostream>
#include <string.h>
#include <map>
#include <vector>
using namespace std;

string head;
int cnt,total;
map<string,int>weight;
map<string,bool>visit;
map<string,vector<string> >adjlist;
map<string,int>res;

void DFS(string start)
{
    visit[start]=1;
    cnt++;
    total+=weight[start];
    if(weight[start]>weight[head])head=start;
    vector<string>::iterator it=adjlist[start].begin();

    for(;it!=adjlist[start].end();it++)
    {
       if(visit[*it]==0)
       {
           DFS(*it);
       }
    }
}
int main()
{
    int N,K,T,i=0;
    cin>>N>>K;
    string member1,member2;
    while(i<N)
    {
        cin>>member1>>member2>>T;
        weight[member1]+=T;
        weight[member2]+=T;
        adjlist[member1].push_back(member2);
        adjlist[member2].push_back(member1);
        visit[member1]=0;
        visit[member2]=0;
        i++;
    }

    map<string,bool>::iterator ite=visit.begin();
    for(;ite!=visit.end();ite++)
    {
        if(ite->second==0)
        {
            total=0;
            cnt=0;
            head=ite->first;
            DFS(ite->first);
        }
        if(cnt>2&&total/2>K)res[head]=cnt;
    }
    map<string,int>::iterator it=res.begin();
    cout<<res.size()<<endl;
    for(;it!=res.end();it++)cout<<it->first<<" "<<it->second<<endl;
    return 0;
}
本文参考: http://blog.csdn.net/iaccepted/article/details/20161235

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值