【一隻蒟蒻的刷題歷程】 【PAT】 A1034 團伙頭

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

題意:

警察找到團伙頭的一種方法是檢查人們的電話。如果A和B之間有電話,我們說A和B是相關的。關係的權重定義爲兩個人之間進行的所有電話呼叫的總時間長度。 “幫派”是由兩個以上彼此相關的人員組成的集羣,總關係權重大於給定的閾值K。在每個幫派中,總權重最大的是頭。現在給出電話列表,您應該找到幫派和團長。

輸入規格:

每個輸入文件包含一個測試用例。對於每種情況,第一行都包含兩個正數N和K(均小於或等於1000),電話數量和權重閾值。然後N行,每行採用以下格式:

名稱1 名稱2 時間

其中Name1和Name2是通話兩端的人員名稱,Time是通話時間。名稱是從A-Z中選擇的三個大寫字母的字符串。時間長度是一個不超過1000分鐘的正整數。

輸出規格:

對於每個測試用例,首先在一行中打印幫派總數。然後,對於每個團伙,在一行中打印頭的名稱和成員總數。可以確保每個幫派頭都是唯一的。必須根據標題名稱的字母順序對輸出進行排序。

樣本輸入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

樣本輸出1:

2
AAA 3
GGG 3

樣本輸入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

樣本輸出2:

0

代碼:

#include <iostream>
#include <algorithm>
#include <vector>
#include <cstdio>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <queue>
#include <set>
#include <map>
using namespace std; 
const int maxn=2050;
int n,k,T[maxn]; //通話記錄,閾值
int g[maxn][maxn]={0}; //存圖 
bool vis[maxn]={false}; //標記是否被訪問 
map<string,int> m1; //名字-編號
map<int,string> m2; //編號-名字 
map<string,int> ans; //頭目-團伙數量
int num=0; //總人數
int zhuan(string s)
{
     if(m1.find(s) != m1.end()) //這個名稱已經被換成編號了
	 	return m1[s];  //返回編號 
	 else 
	   {
	   	   m1[s] = num;    //s對應編號num 
		   m2[num] = s;    //編號num對應s 
		   return num++;   //給編號 
	   }	  
} 

void dfs(int u,int &head,int &member,int &numk)
 //遍歷連通塊
{
	vis[u]=1;    //標記訪問過
	member++;   //該團伙成員數量++
	if(T[u] > T[head]) //找最大電話時間的是頭頭
	   head = u;
	for(int i=0;i<num;i++)  //遍歷每個人
	{
      if(g[u][i]>0)  //走得通(有電話交流)
      {
		numk += g[u][i];  //總邊權增加
		g[u][i] = g[i][u]=0;   //讓這條邊走不通,防止後面再走
		if(vis[i]==false)   //沒訪問過,就去訪問
		    dfs(i,head,member,numk);
	}
    }
}


int main() 
{ 
  int n,k;
  cin>>n>>k;
  string a,b;
  int t; 
  while(n--)
  {
  	  cin>>a>>b>>t;
  	  int x=zhuan(a),y=zhuan(b);
	  g[x][y] += t;	 //無向圖 
      g[y][x] += t;
      T[x] += t;   //累加個人時間 
      T[y] += t;
  } 
  
  for(int i=0;i<num;i++)
  {
  	 if(vis[i]==false) 
  	 {
  	 	int head=i,member=0,numk=0; //頭頭,成員數,總邊權
  	 	dfs(i,head,member,numk);
  	 	if(numk>k && member>2) //總邊權大於閾值k,成員大於2個爲團伙
  	 		ans[m2[head]] = member; //更新
	 }
  }
  
  cout<<ans.size()<<endl; //格式輸出
  for(auto it=ans.begin();it!=ans.end();it++)
    cout<<it->first<<" "<<it->second<<endl;
  return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章