标签:字典 图片 r++ return lse value font ace 邻接表
大致题意就是给出 N对 人的通话记录,可以根据通话对象分成若干个组(连通图)。在一个连通图中,任意两个人之间的总通话时长表示边权,一个人参与的总通话时长表示点权,所有人的总通话时长表示总边权。现在给定一个阀值K,且只要连通图的总边权超过K,并满足成员数超过2,则该组视为“犯罪团伙”,而且该组内点权最大的人 视为头目。要求输出“犯罪团伙”的个数,并按头目姓名字典序从小到大的顺序输出每个“犯罪团伙”的头目姓名和成员数。
思路:
第一步,建立姓名与编号的映射关系。(难点)
map<string,int> stringToint;//姓名-编号
map<int,string> intTostring;//编号-姓名
第二步,保存每个人的点权(一个人参与的总通话时长),保存边权(任意两个人之间的总通话时长)。
(涉及图的DFS时,通常需要一个邻接矩阵(邻接表)、一个顶点表、一个标记是否被访问表)
int G[maxn][maxn] = {0}; //保存边权,邻接矩阵
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() {//遍历图的所有连通块,获取gang信息 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 }
ps:说实话这道题很难,可能是因为刚开始复习图的知识,很多内容需要花时间慢慢熟悉吧。
标签:字典 图片 r++ return lse value font ace 邻接表
原文地址:https://www.cnblogs.com/keep23456/p/12425749.html