题目
思路
题目大意:给一张网络图,找到连通块,并找到每个连通块中权值最大的元素,作为头领输出;
这道题本身并不难,但有几个点要注意:
1、给的名字是string型的,并不是下标,所以要用map转化一下;
2、使用DFS进行遍历时,对于当前的节点,连接其边的权值在对当前节点进行DFS时已经加入了,为了避免有环图边值重复加的情况,每一条边在遍历过后就要删去,避免走回头路;
3、每个人都有一个权值,所以需要开一个额外的weight数组记录每个用户的权值;
代码
#include <iostream>
#include <vector>
#include <stack>
#include <queue>
#include <algorithm>
#include <cstring>
#include <string>
#include <math.h>
#include <set>
#include <map>
using namespace std;
const int maxn = 2010;
int graph[maxn][maxn] = {0}, weight[maxn] = {0};
map<string, int> strToInt;
map<int,string> intToStr;
map<string, int> gang;
int numPerson = 0, n, k;
bool vis[maxn];
int change(string name){
//如果找到了,直接返回
if(strToInt.find(name) != strToInt.end()) return strToInt[name];
//没有找到,添进去
strToInt[name] = numPerson;
intToStr[numPerson] = name;
return numPerson ++;
}
void DFS(int nowVisit, int& head, int& num, int& total){
num ++;
vis[nowVisit] = true;
if(weight[nowVisit] > weight[head]) head = nowVisit;
for(int i = 0; i < numPerson; i ++){
//代表有联系
if(graph[nowVisit][i] > 0){
total += graph[nowVisit][i];
graph[nowVisit][i] = graph[i][nowVisit] = 0;//删掉这条边,防止走回头路
if(vis[i] == false){
DFS(i, head, num, total);
}
}
}
}
int main()
{
//初始化
//fill(graph, graph + maxn * maxn, 0);
fill(vis, vis + maxn, false);
scanf("%d%d", &n, &k);
int time;
string str1, str2;
//读入信息
for(int i = 0; i < n; i ++){
cin >> str1 >> str2 >> time;
int u = change(str1);
int v = change(str2);
graph[u][v] += time;
graph[v][u] += time;
weight[u] += time;
weight[v] += time;
}
//对每个点开始进行DFS,寻找连通块
for(int i = 0; i < numPerson; i ++){
int head = i, num = 0, total = 0;
if(vis[i] == false){
DFS(i, head, num, total);
}
if(num > 2 && total > k){
gang[intToStr[head]] = num;
}
}
//输出结果
printf("%d\n", gang.size());
for(auto it = gang.begin(); it != gang.end(); it ++){
cout << it->first << " " << it->second << endl;
}
system("pause");
return 0;
}