[PAT] A1034 Head of a Gang

tech2022-09-05  109

(重要!) 图的DFS遍历;map的使用

思路

方法一

算法笔记第355页

方法二

法一中的点权和边权其实是一个东西,用一个map存起来就好,输入的时候如果a和b有通话,则a的点权和b的点权都加上通话时长,且将一条边插入图中(无需知道边长,图用map<string, vector >保存,这样直接以人名对应,比较方便。vector里存的是与键有通话记录的人名,插入时记得遍历一次若无记录才插入,避免重复)。一次DFS遍历得出一个连通图的成员,用vector 保存人名,这样顺便也可直接获取人数。连通图各个结点的点值相加再除以二即整个连通图的通话时长总和,这样也避免了遍历图计算边权重复的问题。最后将头目姓名和人数存在一个map中,map会自动排序,直接输出即可。

AC代码

方法一

#define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<iostream> #include<string> #include<string.h> #include<vector> #include<map> using namespace std; #define MAX 2010 map<string, int>strtoint; map<int, string>inttostr; map<string, int>gang; int G[MAX][MAX] = { 0 }; int weight[MAX] = { 0 }; bool vis[MAX] = { false }; int n, threshold; int numPerson = 0; void DFS(int now, int& head, int& member, int& total) { vis[now] = true; member++; if (weight[now] > weight[head]) head = now; for (int i = 0;i < numPerson;i++) { if (G[now][i] > 0) { total += G[now][i]; G[now][i] = G[i][now] = 0; if (vis[i] == false) DFS(i, head, member, total); } } } void DFSTrave() { int i; for (i = 0;i < numPerson;i++) { if (vis[i] == false) { int head = i, member = 0, total = 0; DFS(i, head, member, total); if (member > 2 && total > threshold) { gang[inttostr[head]] = member; } } } } int change(string str) { if (strtoint.find(str) != strtoint.end()) { return strtoint[str]; } else { strtoint[str] = numPerson; inttostr[numPerson] = str; return numPerson++; } } int main() { scanf("%d%d", &n, &threshold); int i; for (i = 0;i < n;i++) { string str1, str2; int w; cin >> str1 >> str2 >> w; int id1 = change(str1); int id2 = change(str2); G[id1][id2] += w; G[id2][id1] += w; weight[id1] += w; weight[id2] += w; } DFSTrave(); map<string, int>::iterator it; cout << gang.size() << endl; for (it = gang.begin();it != gang.end();it++) { cout << it->first << " " << it->second << endl; } return 0; }

方法二

#define _CRT_SECURE_NO_WARNINGS #include<iostream> #include<cstdio> #include<string> #include<map> #include<vector> #include<algorithm> using namespace std; map<string, int>Gang;//键:头目名;值:人数(满足人数>2,并且通话总时长大于给定值) map<string, vector<string>>mp; map<string, int>vis; vector<string>tmember;//临时存储每个连通图的成员 map<string, int>headtime;//每个人的通话总时长 void DFS(string s) { vis[s] = true; tmember.push_back(s); for (int i = 0;i < mp[s].size();i++) if (vis[mp[s][i]] == false) DFS(mp[s][i]); } int main() { int i, j, n, time, threshold; string head; scanf("%d%d", &n, &threshold); for (i = 0;i < n;i++) { string name1, name2; cin >> name1 >> name2 >> time; headtime[name1] += time; headtime[name2] += time; vis[name1] = vis[name2] = false; for (j = 0;j < mp[name1].size();j++) if (mp[name1][j] == name2) break; if (j == mp[name1].size()) mp[name1].push_back(name2); for (int j = 0;j < mp[name2].size();j++) if (mp[name2][j] == name1) break; if (j == mp[name2].size()) mp[name2].push_back(name1); } for (auto it = mp.begin();it != mp.end();it++) { if (vis[it->first] == false) { tmember.clear(); DFS(it->first); int sumtime = 0; for (i = 0;i < tmember.size();i++) sumtime += headtime[tmember[i]]; sumtime = sumtime / 2; if (sumtime > threshold && tmember.size() > 2) { time = headtime[tmember[0]]; head = tmember[0]; for (i = 1;i < tmember.size();i++) //找头目:通话多的。 if (headtime[tmember[i]] > time) { head = tmember[i]; time = headtime[tmember[i]]; } Gang[head] = tmember.size(); } } } printf("%d\n", Gang.size()); for (auto it = Gang.begin();it != Gang.end();it++) cout << it->first << " " << it->second << endl; return 0; }
最新回复(0)