zoukankan      html  css  js  c++  java
  • 1034. Head of a Gang

    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.

    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

    基本思路

    本题是连通分支算法的一个变种, 不但需要找到连通分支,还要找到该连通分支中度最大的,我采用的方法是每次dfs的时候将本次dfs搜索到的点加入一个vector中,dfs结束,搜索该vector中度最大的节点,但是不要忘了用完以后需要清除vector,否则会重复搜索。

    关于名字与节点编码的映射:

    本题使用了两个map, 一个用于名字-编码的映射, 一个用于编码-名字映射,若name字段大于3个字符, 可以节省很大的空间,不过就这题而言,开一个26 * 26 * 26的数组未尝不可,也省去了hash的成本,具体的没有尝试过,不知道能不能AC
    此题源码如下:

    #include <iostream>
    #include <vector>
    #include <string.h>
    #include <string>
    #include <algorithm>
    #include <map>
    
    #define M 26 * 26 * 26
    using namespace std;
    
    typedef struct
    {
        int v;
        int w;
    } Edge;
    
    typedef struct
    {
        string name;
        int cnt;
    }Res;
    
    int cmp(Res r1, Res r2)
    {
        return r1.name < r2.name;
    }
    vector< vector<Edge> > edge;
    vector<Res> res;
    map<int, string> i_s; //编码-名字映射
    map<string, int> s_i; //名字-编码映射
    
    int idx = 1;
    int N, th;
    int weight[M];
    
    void init()
    {
        cin >> N >> th;
        edge.resize(M);
        memset(weight, 0, sizeof(weight));
        //邻接链表初始化
        while(N--)
        {
            int time;
            string begin, end;
            cin >> begin >> end >> time;
            if(s_i[begin] == 0)
            {
                i_s[idx] = begin;
                s_i[begin] = idx++;
            }
            if(s_i[end] == 0)
            {
                i_s[idx] = end;
                s_i[end] = idx++;
            }
            int u = s_i[begin];
            int v = s_i[end];
    
            Edge e;
            e.v = v;
            e.w = time;
            edge[u].push_back(e);
            weight[u] += time;//计算度
            weight[v] += time;
        }
    }
    
    int vst[M];
    vector<int> sear;
    
    int dfs(int v)
    {
        if(vst[v])
            return 0;
    
        vst[v] = 1;
    
        sear.push_back(v); //这里把本次搜索到的点加入vector
        int sum = 0;
        for(int i = 0; i < edge[v].size(); i++)
        {
            sum += edge[v][i].w;
            sum += dfs(edge[v][i].v);
        }
        return sum;
    }
    
    int main()
    {
        init();
        memset(vst, 0, sizeof(vst));
        for(int i = 1; i < idx; i++)
        {
            int t = dfs(i); //dfs
    
            if(t > th && sear.size() > 2)
            {
                int max = -1;
                int id = 0;
                for(int j = 0; j < sear.size(); j++)
                {
                    //搜索最大值
                    if(weight[sear[j]] > max)
                    {
                        max = weight[sear[j]];
                        id = sear[j];
                    }
                }
                Res r;
                r.name = i_s[id];
                r.cnt = sear.size();
                res.push_back(r);   //这个不能忘记
            }
            sear.clear();
        }
    
        sort(res.begin(), res.end(), cmp);
        //结果输出
        cout << res.size() << endl;
        if(res.size() > 0)
        {
            for(int i = 0; i< res.size(); i++)
            {
                cout << res[i].name << " " << res[i].cnt << endl;
            }
        }
        return 0;
    }
    
  • 相关阅读:
    ASP.NET MVC 以Stream 下载文件
    ITextSharp 初次接触
    Easyui中tree组件实现搜索定位功能及展开节点定位
    lodop 打印控件的使用
    XML IList<T> TO DataSet TO DataTable 相互转换
    JSONToObejct 问题 part 1
    可以动态添加图片的轮播插件
    防止机器注册
    sqlServer 取每组的前几条数据
    log4net 动态设定日志文件名
  • 原文地址:https://www.cnblogs.com/princecoding/p/5840090.html
Copyright © 2011-2022 走看看