甲级 1034 - Head of a Gang123

题目:456

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 threthold 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.

Input Specification:

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 threthold, 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.

Output Specification:

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

题意:
   给出一些通话记录,若A和B有通话记录,则A与B有关系,有通话关系的一群人的通话时间之和若超过一个阈值且人数大于2,则称为一个黑帮,其中通话时间最长的是黑帮老大。现在要你根据通话记录给出可调查出的黑帮人数及黑帮大佬名字。通话人名为一个有三个大写字母(A-Z)组成的字符串

解题思路:
   用并查集存各个区块,然后再求和,看人数及通话个数满不满足情况,满足则按字典序输出

这里由于名字是字符串,并不好直接使用并查集(当然可以用map<string,int>,但是耗时),由于名字是固定的三个大写字母构成,所以可以看做是一个26进制数(0-‘A’,1-'B'...),把相应名字转化为10进制数即可存入int Set【】数组中.

这里学到一点:固定长度,且元素固定在一个范围内(比如本题的'A'-'Z'),可以将名字数值化,便于存储与读取

AC代码:
#include<iostream>
#include<string>
#include<sstream>
#include<stack>
#include<map>
#include<iomanip>
#include<algorithm>
#include<cmath>
#include<queue>
#include<set>
#define maxSize 26*26*26
using namespace std;
//甲级 1034 并查集
//因为名字是字符串,需要将名字离散化,可以利用26进制转化为10进制来转化

int stringToInt(string name){
    int result = 0;
    for(int i=0;i<(int)name.length();i++){
        result*=26;
        result+=name[i]-'A';
    }
    return result;
}

string intToString(int id){
    string result = "";
    for(int i=0;i<3;i++){
        if(id==0)
            result+='A';
        else{
            result += id%26 + 'A';
            id/=26;
        }
    }
    reverse(result.begin(),result.end());
    return result;
}

int Set[maxSize];
int t[maxSize];

int Find(int i){//改进版
    if(Set[i]!=i)
        Set[i] = Find(Set[i]);
    return Set[i];
}

void Add(int left,int right){
    int pl,pr;
    pl = Find(left);
    pr = Find(right);
    if(pl==pr)
        return;
    //将右边加入左边
    Set[pr] = pl;
}

struct Result{
    string head;
    int amt;
    Result(string H,int A):head(H),amt(A){}
    friend bool operator<(Result a,Result b){
        return a.head>b.head;
    }
};

int main()
{
    int eAmt,threthold;
    set<int> people;
    while(cin>>eAmt>>threthold){
        int time;
        for(int i=0;i<maxSize;i++)
            Set[i] = i;
        fill(t,t+maxSize,0);//初始化时间为0
        string left,right;
        while(eAmt--){
            cin>>left>>right>>time;
            int leftId,rightId;//预存,防止函数多次调用
            leftId = stringToInt(left);
            rightId = stringToInt(right);
            t[leftId] += time;
            t[rightId] += time;
            Add(leftId,rightId);
            people.insert(leftId);
            people.insert(rightId);
        }
        priority_queue<Result> rs;
        for(set<int>::iterator it = people.begin();it!=people.end();it++){
            //cout<<intToString(*it)<<" "<<*it<<" "<<Find[*it]<<" "<<t[*it]<<endl;

            if(Set[*it]==*it){//默认按照字典序排列的
                int Count = 0;
                int amt = 0;
                int maxId = *it,Max = t[*it];
                for(set<int>::iterator Init = people.begin();Init!=people.end();Init++){
                    if(Find(*Init)==*it){
                        amt++;
                        Count+=t[*Init];
                        if(t[*Init]>Max){
                            Max = t[*Init];
                            maxId = *Init;
                        }
                    }
                }
                Count/=2;
                if(amt>2&&Count>threthold){
                    rs.push(Result(intToString(maxId),amt));
                }
            }
        }

        cout<<(int)rs.size()<<endl;
        while(rs.empty()==false){
            Result r = rs.top();
            cout<<r.head<<" "<<r.amt<<endl;
            rs.pop();
        }
    }
    return 0;
}

 

posted @ 2019-03-13 21:54  巴特曼  阅读(126)  评论(0编辑  收藏  举报