您的位置:首页 > 其它

1034. Head of a Gang (30)

2017-08-14 18:30 218 查看
One way that the police finds the head of a gang is to check people’s phone calls. If there is a phone call between A and B, we say that A and B is related. The weight of a relation is defined to be the total time length of all the phone calls made between the two persons. A “Gang” is a cluster of more than 2 persons who are related to each other with total relation weight being greater than a given threshold K. In each gang, the one with maximum total weight is the head. Now given a list of phone calls, you are supposed to find the gangs and the heads.

Input Specification:

Each input file contains one test case. For each case, the first line contains two positive numbers N and K (both less than or equal to 1000), the number of phone calls and the weight threthold, respectively. Then N lines follow, each in the following format:

Name1 Name2 Time

where Name1 and Name2 are the names of people at the two ends of the call, and Time is the length of the call. A name is a string of three capital letters chosen from A-Z. A time length is a positive integer which is no more than 1000 minutes.

Output Specification:

For each test case, first print in a line the total number of gangs. Then for each gang, print in a line the name of the head and the total number of the members. It is guaranteed that the head is unique for each gang. The output must be sorted according to the alphabetical order of the names of the heads.

Sample Input 1:

8 59

AAA BBB 10

BBB AAA 20

AAA CCC 40

DDD EEE 5

EEE DDD 70

FFF GGG 30

GGG HHH 20

HHH FFF 10

Sample Output 1:

2

AAA 3

GGG 3

Sample Input 2:

8 70

AAA BBB 10

BBB AAA 20

AAA CCC 40

DDD EEE 5

EEE DDD 70

FFF GGG 30

GGG HHH 20

HHH FFF 10

Sample Output 2:

0

算法分析:本题主要考察图的遍历,我选择深度优先搜索。(1)由于输入的字符串,C不像Python有字典那种神器,所以我们需要把字符串转换为数值;(2)找到一个连通图(一个团伙Gang);(3)然后调用DFS,同时记录每个点的权值,然后选出具有最大权值的点作为老大。再返回(2)直到找遍所有的点。具体的见代码注释。

#include <stdio.h>
#include <stdlib.h>

int g[2010][2010] = {{0}};
int map[20000] = {0}, hash[2010] = {0}, visited[2010] = {0};
int temp = 1, np, n, k, total;

typedef struct Gang *tmp;
struct Gang
{
int boss; //一个团伙中老大是谁
int num; //团伙成员的数量
}gang[1000];

int cmp(const void *a, const void *b)
{
tmp aa = (tmp)a;
tmp bb = (tmp)b;
return (aa->boss > bb->boss) ? 1 : -1;
}

int strToNum(char s[]) //把字符串映射成数值,为了保证一一映射,把字符看成是26进制的数。
{
int num = (s[0] - 'A') * 26 * 26 + (s[1] - 'A') * 26 + (s[2] - 'A'); //转换成10进制
if(map[num] == 0) //如果这个数第一次出现
{
map[num] = temp; //temp是一个初始化为0的数。把10进制数映射成0。
hash[temp] = num; //互相映射
return temp++; //返回num的下标
}
else //如果这个数之前出现过,就返回num的下标
return map[num];
}

void dfs(int v, int ev[])
{
int w;
visited[v] = 1;
for(w = 1; w <= n; w++)
{
if(g[v][w] > 0)
{
ev[v] += g[v][w]; //ev数组存储每个节点的权值
//这里要一次存相邻的两个节点的权值,如果不这样做,当图中出现回路时就有节点记录不到权值。
ev[w] += g[v][w];
total += g[v][w];
g[v][w] = g[w][v] = 0; //权值清零,防止遍历重复的节点
if(!visited[w])
np++; //记录一个连接图中节点的数量
dfs(w, ev);
}
}
}

void solve()
{
int v, s = 0;
for(v = 1; v <= n; v++)
{
if(!visited[v])
{
int ev[1001] = {0}, i;
np = 1;
total = 0;
dfs(v, ev);
if(np > 2 && total > k) //满足成为一个团伙的条件
{
int boss = 1, max = ev[1];
for(i = 2; i <= n; i++) //找出团伙中的老大
if(ev[i] > max)
{
boss = i;
max = ev[i];
}
gang[s].boss = hash[boss];
gang[s].num = np;
s++;
}
}
}
qsort(gang, s, sizeof(gang[0]), cmp); //按老大编号从小到大排序
printf("%d\n", s);
int i;
for(i = 0; i < s; i++)
{
char head[3];
int j = 2, t = gang[i].boss;
while(j >= 0) //完成数值到字符串的映射
{
head[j
4000
--] = (t % 26) + 'A';
t /= 26;
}
printf("%s %d\n", head, gang[i].num);
}
}

int main()
{
int i;
scanf("%d %d", &n, &k);
for(i = 0; i < n; i++)
{
char p1[4], p2[4];
int w, v1, v2;
scanf("%s %s %d", p1, p2, &w);
v1 = strToNum(p1);
v2 = strToNum(p2);
g[v1][v2] = w;
if(g[v2][v1] != 0) //这个图还是无向图,需要把A到B和B到A的有向边权值合并为一个无向边
{
g[v1][v2] += g[v2][v1];
g[v2][v1] = g[v1][v2];
}
else
g[v2][v1] = w;
}
solve();

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  PAT甲级