【PAT】1034.Head of a Gang (30)【深度优先搜索】

题目描述

One way that the police finds the head of a gang is to check people’s phone calls. If there is a phone call between A and B, we say that A and B is related. The weight of a relation is defined to be the total time length of all the phone calls made between the two persons. A “Gang” is a cluster of more than 2 persons who are related to each other with total relation weight being greater than a given threshold K. In each gang, the one with maximum total weight is the head. Now given a list of phone calls, you are supposed to find the gangs and the heads.

翻译:警察寻找一个帮派的首领时其中一个方法就是检查人们的通话记录。如果A和B有一个通话记录,我们就说A和B是相连的。一个关系的权重为这两个人之间的总通话时长。如果有超过2个人相互有联系并且总联系权重大于给的门槛K,我们就称之为一个“帮派”。在每个帮派中,拥有最高权重的人就是首领。现在给你一个通话记录表,你需要找到其中的帮派及其首领。

INPUT FORMAT

Each input file contains one test case. For each case, the first line contains two positive numbers N and K (both less than or equal to 1000), the number of phone calls and the weight threshold, respectively. Then N lines follow, each in the following format:

Name1 Name2 Time

where Name1 and Name2 are the names of people at the two ends of the call, and Time is the length of the call. A name is a string of three capital letters chosen from A-Z. A time length is a positive integer which is no more than 1000 minutes.

翻译:每个输入文件包含一组测试数据。对于每组输入数据,第一行包括两个正整数N和K(都小于等于1000),分别代表电话记录数和权重门槛。接下来的N行,每行都为以下格式:
Name1 Name2 Time
姓名1和姓名2代表电话记录的两边,时间代表通话时长。姓名为一个包含3个从A到Z的大小字母的字符串。时间长度是一个不超过1000分钟的正整数。

OUTPUT FORMAT

For each test case, first print in a line the total number of gangs. Then for each gang, print in a line the name of the head and the total number of the members. It is guaranteed that the head is unique for each gang. The output must be sorted according to the alphabetical order of the names of the heads.

翻译:对于每组输入数据,首先输出一行帮派的总个数。接下来对于每个帮派,输出一行首领的姓名和该帮派总人数。数据保证每个帮派首领唯一。输出必须按照首领的名字的字母序排序。


Sample Input 1:

8 59
AAA BBB 10
BBB AAA 20
AAA CCC 40
DDD EEE 5
EEE DDD 70
FFF GGG 30
GGG HHH 20
HHH FFF 10

Sample Output 1:

2
AAA 3
GGG 3


Sample Input 2:

8 70
AAA BBB 10
BBB AAA 20
AAA CCC 40
DDD EEE 5
EEE DDD 70
FFF GGG 30
GGG HHH 20
HHH FFF 10

Sample Output 2:

0


解题思路

先用map容器和string数组将名字和编号相对应。然后建立关系矩阵,进行深度优先搜索。如果该次深搜的总权重大于K,则将记录的首领名和帮派总人数保存到优先队列中。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<string>
#include<map> 
#include<queue>
#include<algorithm>
#define INF 99999999
using namespace std;
int N,K,ccount=1;
map<string,int> mp;//将人名保存为数字编号
string name[2010];//记录数字编号对应的人名
typedef pair<string,int> P;
priority_queue<P,vector<P>,greater<P> > q;//优先队列保存首领
int G[2010][2010];//记录关系表
int visited[2010];//记录节点是否访问过
int head,headsum,people;//记录临时的首领编号,对应权重和该帮派总人员
int dfs(int a){
    visited[a]=1;
    int sum=0,tcount=0,tsum=0;
    for(int i=1;i<ccount;i++){
        if(G[a][i]){
            sum+=G[a][i];
            tsum+=G[a][i];
            if(!visited[i])sum+=dfs(i),people++;//如果节点未访问过则深搜,总人数加一
            tcount++;
        }
    }
    if(tcount>=2&&tsum>headsum){
        headsum=tsum;
        head=a;
    }
    return sum;
}
int main(){
    scanf("%d%d",&N,&K);
    string n1,n2;
    int time;
    for(int i=0;i<N;i++){
        cin>>n1>>n2;
        if(!mp[n1])mp[n1]=ccount++,name[mp[n1]]=n1;
        if(!mp[n2])mp[n2]=ccount++,name[mp[n2]]=n2;
        int t1=mp[n1],t2=mp[n2];
        scanf("%d",&time);
        G[t1][t2]=G[t2][t1]+=time;
    }
    for(int i=1;i<ccount;i++){
        head=headsum=people=0;
        if(!visited[i]){
            if(dfs(i)>K*2){//每次通话计算了两遍
                if(head!=0){
                    q.push(P(name[head],people+1));
                }
            }
        }
    }
    cout<<q.size()<<endl;
    while(!q.empty()){
        P temp=q.top();q.pop();
        cout<<temp.first<<" "<<temp.second<<endl;
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值