九度 題目1446:Head of a Gang

九度 題目1446:Head of a Gang

原題OJ鏈接:http://ac.jobdu.com/problem.php?pid=1446

題目描述:

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 threthold 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.

輸入:

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.

樣例輸入:

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
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
AAA 3
GGG 3
0

解題思路:

題目意思:每組首先輸入邊的個數 N 和一個閾值 K。接下來輸入每一條邊的信息,兩個結點 A, B,然後是這條邊的權重Time。兩個結點的名字必須是三個大寫英文字母組成,所以在代碼中使用了STL中的map映射,將每一個結點的英文字符串映射到一個獨一無二的數字結點。
在這個圖中,尋找連通分量,該連通分量中權重之和大於閾值K,且所包含結點個數大於2。
輸出:第一行是滿足上述條件連通分量的個數,第二行之後每一行輸出每一個連通分量中 最大的結點(該結點與其他結點相連的權重之和最大)名稱和該連通分量中結點個數。

源代碼:

#include<iostream>
#include<cstring>
#include<map>
#include<algorithm>
using namespace std;
#define MAX_N 1005
int Tree[MAX_N];
int sum[MAX_N]; 
/*記錄每一個結點的權重和,把一個並查集合中權重之和存儲到根結點上,
若結點 i 爲根結點,則sum[i]爲該並查集合中的邊的權重之和*/

int member[MAX_N];
/*記錄所在並查集合中結點個數,存儲在根結點上
若結點 i 爲根結點,則member[i]爲該並查集合中結點個數*/

string ans[MAX_N]; //與map相反映射
map <string,int> Map;// Map["AAA"]=1,ans[1]="AAA"; 
map <string,int>::iterator iter;

int gangRoot[MAX_N][2];
/*gangRoot[i][0]存儲每一個cluster中的根結點,
gangRoot[i][1]存儲該cluster中結點個數
*/

int value[MAX_N];//記錄每個結點的time
/*例如樣例一中,把AAA,BBB,CCC分別映射爲結點1,2,3
則value[1]=70,value[2]=30,value[3]=40*/


struct POS{
    string str;
    int num;
} pos[MAX_N];
/*該結構體數組存儲每一個cluster中的head,
string類型的結點名字和該結點所在cluster中的結點個數num
*/

bool cmp(POS a,POS b){
    return a.str<b.str;
}//sort()函數中的比較函數,即輸出head結點按字母表排序

int findRoot(int x){//尋找根結點
    if(Tree[x]==-1) return x;
    else{
        int tmp=findRoot(Tree[x]);
        Tree[x]=tmp;
        return tmp;
    }
}

int main(){
    int N,K,time;
    string name1,name2;
    while(cin>>N>>K){
        for(int i=0;i<MAX_N;i++){
            Tree[i]=-1;
            sum[i]=0;
            member[i]=1;
            ans[i]="";
            value[i]=0;
        }
        for(iter=Map.begin();iter!=Map.end();iter++){
            iter->second=0;
        }//遍歷map,將所有節點初始化爲0

        int node=1;//將字母結點轉化爲數字結點,一一對應,從結點1開始
        for(int i=0;i<N;i++){
            cin>>name1>>name2>>time;
            if(Map[name1]==0){
                Map[name1]=node;//映射,字符——>數字
                ans[node]=name1;//映射,數字——>字符
                node++;
            }
            if(Map[name2]==0){
                Map[name2]=node;
                ans[node]=name2;
                node++;
            }


            int a=Map[name1];
            int b=Map[name2];
            value[a]+=time;
            value[b]+=time;

            a=findRoot(a);
            b=findRoot(b);
            if(a!=b){

                Tree[a]=b;
                member[b]+=member[a];
                sum[b]=sum[b]+sum[a]+time;
            }

            else{//若這兩個結點已經存在一條邊,只是累加權重,成員數保持不變
                sum[a]+=time;
            }           
        }


        int count=0;
        memset(gangRoot,0,sizeof(gangRoot));
        for(int i=1;i<node;i++){
            if(Tree[i]==-1 && sum[i]>K && member[i]>2){
                gangRoot[count][0]=i;
                gangRoot[count][1]=member[i];
                count++;               
            }
        }

        cout<<count<<endl;
        for(int i=0;i<count;i++){
            int tmp=0;            
            pos[i].num=gangRoot[i][1];
            for(int j=1;j<node;j++){
                int c=findRoot(j); 
                if(c==gangRoot[i][0] && value[j]>tmp){
                    tmp=value[j];
                    pos[i].str=ans[j];

                }
            }
        }

        sort(pos,pos+count,cmp);//按字母表排序

        for(int i=0;i<count;i++){
            cout<<pos[i].str<<" "<<pos[i].num<<endl;
        }

    }
    return 0;
}

結果截圖:

這裏寫圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章