PAT(甲级)1034 Head of a Gang (30point(s))

题目

题目链接

思路

题目大意:给一张网络图,找到连通块,并找到每个连通块中权值最大的元素,作为头领输出;
这道题本身并不难,但有几个点要注意:
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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值