【九度】题目1446:Head of a Gang

108 篇文章 0 订阅
102 篇文章 5 订阅
题目地址: http://ac.jobdu.com/problem.php?pid=1446
题目描述:
         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.
输入:
         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.
输出:
         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.

样例输入:
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
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
样例输出:
2
AAA 3
GGG 3
0

题目大意:
        确定一个团队队长的方案是看队员彼此之间的通话时间。如果一个团队中,某个队员和其他队员的通话时间是最长的,那么他就是队长。有一些案例,输入为一些人之间的相互通话时间。找出每个案例中的团队个数,团队个数的限制应该是三人以及三人以上,队员之间所有通话时间大于限制时间K,并且需要找出队长和该队的成员个数。 
         基本思路:
        1、如果要使用数组,需要将字母转换为数字,当然最后输出的时候要转换回去。
         2、并查集,读取两个name的时候,就合并。
         3、求父节点,并且算出集合个数。
         4、对每个集合做计算,求成员个数。符合条件,保留,不符合条件,忽略。
         5、按照字母序输出结果。
         恩,写的有点泛,再仔细说一下解题思路。
         这道题有2个关键点
         1、如何确定有几个团队,以及每个团队成员有哪些。
         2、在不知道团队成员归属的时候,如何确定团队成员之间的通话时长和每个成员通话时长。
         这两个问题一旦想清楚了,题目就迎刃而解了。
         1、确定团队以及团队成员,并查集,没什么好说的。只要两者之间相互通话,不管是直接的还是间接的,合并。合并结束之后,求每个成员的父节点,根据并查集思想,如果parent[i] = i,那么i就是该团队的父节点,当然这个节点不一定是队长。
         2、确定团队成员之间的通话时长和每个成员通话时长。
         使用数组singleCallTime,来记录一个团队成员相互打电话的时间,当然在一开始,我们并不知道,哪些成员是一个团队的,这个也没关系,不会影响记录。在记录时间的时候,比如有个例子是这样的
         AAA BBB 10
         BBB AAA 20
        记录团队电话时间的时候,只记录左侧的通话时间,也就是这两行记录,我们认为是AAA通话10,BBB通话20,不考虑AAA和BBB的相互关系,这样就不会出现重复。同时,在记录每个成员通话时间的时候,需要两边都记录,也就是AAA BBB 10表示AAA打电话10,BBB也打电话10。这样我们就解决了第2个问题。
        下一步,我们依次循环团队个数,同时在内层循环,判断每个成员是否属于该团队,如果是,就计算每个成员打电话的时间以及团队成员相互之间电话时间,最后判断是否符合要求。
        如果符合要求,排序打印结果,同时注意将数字转换为字符串。

 C++ AC

#include <stdio.h>
#include <map>
#include <vector>
#include <string>
#include <string.h>
#include <algorithm>
#include <list>
using namespace std;
const int maxn = 1002;
int parent[maxn];
int n;
int k;
int i;
int currNum;
map<string , int> baseMap;
char array[maxn][4];
char resultArr[maxn][4];
int callTime[maxn];
int singleCallTime[maxn];
int fatherArr[maxn];
int visit[maxn];
 
struct Node{
    char name[4];
    int size;
}nodes[maxn];
 
//并查集寻找父亲节点
int findParent(int f) {  
    while(parent[f] != f){
        f = parent[f];
    }
    return f;
}  
//并查集合并节点
void unionTwo(int f, int t) {  
             
    int a = findParent(f);  
    int b = findParent(t);  
    if (a == b) return;   
    if (a > b) {     
        parent[a] = b;     
    } else {  
        parent[b] = a;   
    }  
}  
//初始化基本数据,这在以后会用到
void initData(){
    baseMap.clear();
    memset(callTime,0,sizeof(callTime));
    memset(visit,0,sizeof(visit));
    memset(singleCallTime,0,sizeof(singleCallTime));
    memset(fatherArr,0,sizeof(fatherArr));
    for(i = 1; i < maxn ; i++){
        parent[i] = i;
    }
}
//将字符串转为数字,否则后面不太好处理
int getCurrentNum(char c[]) {  
    int num = 0;  
    map<string,int>::iterator it = baseMap.find(c);
    if (it == baseMap.end()) {  
        currNum++;  
        num = currNum;  
        baseMap.insert(make_pair(c,num));
    }else {  
        num = it->second;  
    }  
    return num;  
}  
//记录每个人打电话的时间
void constructData(char a[], char b[], int anum, int bnum, int d) {  
     if (singleCallTime[anum] == 0) {  
        singleCallTime[anum] = d;  
     }else {  
        singleCallTime[anum] += d;  
     }         
     strcpy(array[anum],a);
     strcpy(array[bnum],b);
     callTime[anum] += d;  
     callTime[bnum] += d;  
}  
 
bool cmp(Node node1,Node node2){
    return strcmp(node1.name,node2.name)<0;
}
 
int main(){
    while(scanf("%d%d",&n,&k) != EOF){
        initData();
        currNum = 0;
        char a[4];
        char b[4];
        int d;
        for(i = 0; i < n; i++){
            scanf("%s%s%d",a,b,&d);
        //  printf("%s\n",a);
        //  printf("%s\n",b);
            int anum = getCurrentNum(a);  
            int bnum = getCurrentNum(b);  
        //  printf("%d\n",anum);
        //  printf("%d\n",bnum);
            constructData(a , b, anum , bnum ,d);
            unionTwo(anum,bnum);
        }
         
         
        int tmpk = 1;
        for (i = 1; i < currNum+1; i++) {  
            parent[i] = findParent(i);  
        //  printf("%d\n",parent[i]);
            if(parent[i] == i){
                fatherArr[tmpk] = i;
                tmpk++;
            }
        }  
        //printf("%d\n",tmpk);
        int num = 0;
        for (i = 1; i < tmpk; i++) {  
            int size = 0;
            int allTime = 0;  
            int maxTime = -1;  
            int maxMem = 0;  
            for (int j = 1; j < currNum + 1; j++) {  
                if(fatherArr[i] != 0 && visit[j] == 0){
                    if(parent[j] == fatherArr[i]){
                        size++;
                        allTime += singleCallTime[j];
                        if (callTime[j] > maxTime) {  
                            maxTime = callTime[j];  
                            maxMem = j;  
                        } 
                        visit[j] = 1;
                    }
                }
            }
            if(size < 3){
                continue;
            }
            if(allTime <= k){
                continue;
            }
            strcpy(nodes[num].name,array[maxMem]);
            nodes[num].size = size;
            num++;
        } 
        sort(nodes, nodes + num , cmp);
        printf("%d\n",num);
        for(i = 0; i < num ; i++){
            printf("%s %d",nodes[i].name,nodes[i].size) ;  
        //  printf("%d",nodes[i].size) ; 
            printf("\n");
        }
         
    }
    return 0;
}
/**************************************************************
    Problem: 1446
    User: wangzhenqing
    Language: C++
    Result: Accepted
    Time:30 ms
    Memory:1096 kb
****************************************************************/

Java AC

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.StreamTokenizer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
  
public class Main {
     
    /*
     * 1446
     */
    private static int parent[];
    private static int maxn = 2002;
    private static int currNum , count;
    private static Map<String, Integer> baseMap ;
    private static Map<Integer, List<Integer>> groupMap;
    private static Map<String, Integer> resultMap; 
    private static String array[] ;
    private static String keys[] ;
    private static int callTime[] ,singleCallTime[];
      
    public static void main(String[] args) throws Exception {
        StreamTokenizer st = new StreamTokenizer(new BufferedReader(
                new InputStreamReader(System.in)));
        while (st.nextToken() != StreamTokenizer.TT_EOF) {
            int n = (int)st.nval;
            st.nextToken();
            int k = (int)st.nval;
            initParent(n);
            for (int i = 0; i < n; i++) {
                st.nextToken();
                String a = st.sval;
                st.nextToken();
                String b = st.sval;
                st.nextToken();
                int d = (int)st.nval;
                int anum = getCurrentNum(a);
                int bnum = getCurrentNum(b);
                constructData(a , b, anum , bnum ,d);
                unionTwo(anum, bnum);
            }
            for (int i = 1; i < currNum+1; i++) {
                parent[i] = findParent(i);
            }
//          具体哪个组包含哪些组员  
            divideGroup();
//          判断组员个数是不是大于三人,组内通话时间是否大于k;
            checkNeedResult(k);
//          打印结果
            printfResult();
        }
    }
      
    private static void initParent(int n) {
        parent = new int[maxn];
        for (int i = 1; i < maxn; i++) {
            parent[i] = i;
        }
        baseMap = new HashMap<String, Integer>();
        array = new String[maxn];
        callTime = new int[maxn];
        singleCallTime = new int[maxn];
        currNum = 0;
    }
       
    private static void constructData(String a, String b, int anum, int bnum, int d) {
        if (singleCallTime[anum] == 0) {
            singleCallTime[anum] = d;
        }else {
            singleCallTime[anum] += d;
        }
          
        array[anum] = a;
        array[bnum] = b;
        callTime[anum] += d;
        callTime[bnum] += d;
    }
      
      
    private static void divideGroup() {
        groupMap = new HashMap<Integer, List<Integer>>();
        for (int i = 1; i < currNum+1; i++) {
            List<Integer> groupMems = null;
            if (groupMap.containsKey(parent[i])) {
                groupMems = groupMap.get(parent[i]);
            }else {
                groupMems = new ArrayList<Integer>();
            }
            groupMems.add(i);
            groupMap.put(parent[i], groupMems);
        }
    }
  
    private static void checkNeedResult(int k) {
        keys = new String[currNum+1];
        count = 0;
        resultMap = new HashMap<String, Integer>();  
        for(Entry<Integer, List<Integer>> entry : groupMap.entrySet()){
            List<Integer> groupMems = entry.getValue();
            int size = groupMems.size();
            if (size < 3) {
                continue;
            }
            int allTime = 0;
            int maxTime = -1;
            int maxMem = 0;
            for (int i = 0; i < size; i++) {
                int mem = groupMems.get(i);
                allTime += singleCallTime[mem];
                if (callTime[mem] > maxTime) {
                    maxTime = callTime[mem];
                    maxMem = mem;
                }
            }
            if (allTime <= k ) {
                continue;
            }
            resultMap.put(array[maxMem], size);  
            keys[count] = array[maxMem];
            count++;
        }
    }
  
    private static void printfResult() {
        Arrays.sort(keys , 0, count);
        System.out.println(count);
        for (int i = 0; i < count; i++) {
            System.out.println(keys[i]+" "+resultMap.get(keys[i]));
        }
    }
  
    private static int getCurrentNum(String c) {
        int num = 0;
        if (!baseMap.containsKey(c)) {
            currNum++;
            num = currNum;
            baseMap.put(c, num);
        }else {
            num = baseMap.get(c);
        }
        return num;
    }
      
    private static void unionTwo(int f, int t) {
           
        int a = findParent( f );
        int b = findParent( t );
        if (a == b) return; 
        if (a > b) {   
            parent[a] = b;   
         } else {
            parent[b] = a; 
         }
    }
     
    private static int findParent(int f) {
        while (parent[f] != f) {
            f = parent[f];
        }
        return f;
    }
}
 
/**************************************************************
    Problem: 1446
    User: wangzhenqing
    Language: Java
    Result: Accepted
    Time:290 ms
    Memory:28428 kb
****************************************************************/
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值