1034 Head of a Gang

  大致题意就是给出 N对 人的通话记录,可以根据通话对象分成若干个组(连通图)。在一个连通图中,任意两个人之间的总通话时长表示边权,一个人参与的总通话时长表示点权,所有人的总通话时长表示总边权。现在给定一个阀值K,且只要连通图的总边权超过K,并满足成员数超过2,则该组视为“犯罪团伙”,而且该组内点权最大的人 视为头目。要求输出“犯罪团伙”的个数,并按头目姓名字典序从小到大的顺序输出每个“犯罪团伙”的头目姓名和成员数。

思路:

第一步,建立姓名与编号的映射关系。(难点)

  map<string,int> stringToint;//姓名-编号
  map<int,string> intTostring;//编号-姓名

第二步,保存每个人的点权、边权,即一个人参与的总通话时长。(相当于顶点表)

(涉及图的DFS时,通常需要一个邻接矩阵(邻接表)、一个顶点表、一个标记是否被访问表

  int G[maxn][maxn] = {0}; //邻接矩阵G,存放边权

  int weight[maxn] = {0}; //编号-点权

  bool visited[maxn] = {false};//标记是否被访问

第三步,遍历图的每一个连通块,获取每个连通块的头目、成员数、总边权。

  DFS(int nowVisit,int& head,int& numMember,int& totalValue) 

  DFSTrave() ;

第四步,通过第三步可以获得连通块的总边权totalValue。如果totalValue 大于给定阀值 K,且成员数大于2,则说明该连通块是一个团伙,将该团伙信息保存下来。

  map<string,int> gang;//头目-成员数

 1 #include<iostream>
 2 #include<vector>
 3 #include<map>
 4 using namespace std;
 5 const int maxn = 2010;
 6 
 7 int G[maxn][maxn] = {0}; //邻接矩阵G,存放边权
 8 int weight[maxn] = {0}; //编号-点权(顶点表)
 9 bool visited[maxn] = {false};//标记是否被访问
10 
11 map<string,int> stringToint;//姓名-编号
12 map<int,string> intTostring;//编号-姓名
13 map<string,int> gang;//头目-成员数
14 
15 int n,k;
16 int numPerson = 0;//编号
17 
18 int change(string str) {
19     if(stringToint.count(str) == 0) {
20         stringToint[str] = numPerson;//姓名-编号
21         intTostring[numPerson] = str;//编号-姓名
22         numPerson++;
23     }
24     return stringToint[str];
25 }
26 void DFS(int nowVisit,int& head,int& numMember,int& totalValue) {
27     numMember++; //成员数加 1
28     visited[nowVisit] = true; //标记nowvisit已访问
29     if(weight[head] < weight[nowVisit]) head = nowVisit;
30     for(int i = 0; i < numPerson; ++i) { //枚举所有人
31         if(G[nowVisit][i] > 0) { //如果能从nowVisit 到达 i
32             totalValue += G[nowVisit][i]; //更新总边权
33             G[nowVisit][i] = G[i][nowVisit] = 0;//删除已访问的边,防止回路遍历
34             if(visited[i] == false) //如果 i未被访问,则递归访问 i
35                 DFS(i,head,numMember,totalValue);
36         }
37     }
38 }
39 
40 void DFSTrave() {//遍历图的所有连通块
41     for(int i = 0; i < numPerson; ++i) {
42         if(visited[i] == false) {
43             int head = i,numMember = 0,totalValue = 0;//头目、成员数、总边权
44             DFS(i,head,numMember,totalValue);
45             if(numMember > 2 && totalValue > k)
46                 gang[intTostring[head]] = numMember;
47         }
48     }
49 }
50 
51 int main() {
52     cin>>n>>k;
53     string name1,name2;
54     int w;
55     for(int i = 0; i < n; ++i) {
56         cin>>name1>>name2>>w;
57         int id1 = change(name1);
58         int id2 = change(name2);
59         weight[id1] += w;
60         weight[id2] += w;
61         G[id1][id2] += w;
62         G[id2][id1] += w;
63     }
64     DFSTrave(); //遍历图的所有连通块,获取gang信息
65     printf("%d\n",gang.size()); //gang的个数 
66     for(auto it = gang.begin(); it != gang.end(); ++it)
67         cout<<it->first<<" "<<it->second<<endl;
68     return 0;
69 }

1034 Head of a Gang

 ps:说实话这道题很难,可能是因为刚开始复习图的知识,很多内容需要花时间慢慢熟悉吧。

上一篇:poj1703


下一篇:静态路由实验(ensp)