1. 程式人生 > 其它 >1034 Head of a Gang

1034 Head of a Gang

一、原題連結

題目詳情 - 1034 Head of a Gang (30 分) (pintia.cn)

二、題面

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.

三、輸入

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.

四、輸出

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.

五、思路

(看了半天沒搞出什麼名堂,翻了翻柳神的筆記)
1. 字串與數值的轉換(模組化的程式碼)
2. 求總的集合個數:考慮dfs
3. 求最大權重點:考慮dfs,關鍵是如何確定哪些點是一個集合的
4. 關於結果的字母序:單獨拎出來排列
---------------------
說下一個柳神程式碼中幾個比較妙的地方:
1. 使用地址符傳入引數(個人平常用慣了全域性變數,這樣確實不好)
2. 關於兩個weight的處理,某人的weight用陣列儲存,隊伍的weight作為dfs的引數使用
3. 隊伍中的最大位次直接進行比較(dfs引數head)
4. 通過map記錄答案:
	* 答案有兩個數
	* 字母序
	* 去重(因為是逐個遍歷下來的)
5. 如何保證每個路徑(不是節點,節點已經用visit標記了):與節點不同,直接將路徑置零即可(這個是我完全沒注意到的細節)


其它帖子的思路還有並查集,即在做合併的時候進來將聯絡時間長的使用者放在後面

六、code

#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <map>
#define INF 0x3f3f3f3f

using namespace std;

const int N=2e3+5;

//特點:對於字串的轉化涉及到字母序,建議統一輸入再處理
//strcmp(a,b):a<b,返回負數;a=b,返回0;a>b,返回正數

int G[N][N],weight[N];

map<int,string> iToS;
map<string,int> sToI;

map<string,int> ansMap;  //結果用一個map儲存,因為輸出有兩個資料,其中string不重複,而map對字串自動排序,同時還可以去重

int num=0,n,m;  //num是語義化的表達,只能從0開始,不能從1
int nameToNum(string name){
    int ans;
    if(sToI.find(name)==sToI.end()){
        sToI[name]=num;
        iToS[num]=name;
        ans=num;
        num++;
    }else{
        ans=sToI[name];
    }
    //cout << "num:" << ans << endl;
    return ans;
}

int visit[N];
void dfs(int now,int &totalNum,int &totalWeight,int &head){  //head妙啊
    //cout << "now:" << now << endl;
    //cout << "totalWeight:" << totalWeight << endl;
    //調整資料
    visit[now]=1;
    totalNum++;
    //cout << "totalNum:" << totalNum << " totalWeight:" << totalWeight << endl;
    if(weight[now]>weight[head]){
        head=now;
    }
    for(int j=0;j<num;j++){
        if(G[now][j]!=0){
            totalWeight+=G[now][j];
            G[now][j]=0;
            G[j][now]=0;
            if(visit[j]==0){
                dfs(j,totalNum,totalWeight,head);   
            }
        }
    }
}

void dfsTravel(){
    for(int i=0;i<num;i++){
        memset(visit,0,sizeof(visit));
        int totalWeight=0,totalNum=0,head=i;
        dfs(i,totalNum,totalWeight,head);
        //cout << "i:" << i << " totalNum:" << totalNum << " totalWeight:" << totalWeight << " head:" << head << endl;
        if(totalNum>2&&totalWeight>m){
            ansMap[iToS[head]]=totalNum;
        }
    }
}

int main(){
    cin >> n >> m;
    string a,b;
    int value;
    for(int i=0;i<n;i++){
        cin >> a >> b >> value;
        int numA=nameToNum(a),numB=nameToNum(b);
        weight[numA]+=value;
        weight[numB]+=value;
        //無向圖
        G[numA][numB]+=value;  //注意這裡看你有重複
        G[numB][numA]+=value;
    }
    dfsTravel();
    cout << ansMap.size() << endl;
    for(auto iterator=ansMap.begin();iterator!=ansMap.end();iterator++){
        cout << iterator->first << " " << iterator->second << endl;
    }
    return 0;
}