[PAT] Grade 1034 Head of a Gang (30 points): traverse a DFS of FIG.

1034 Head of a Gang (30分)

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


Analysis: DFS traversal map

  • Undirected graph (right side interpolation is required twice)

Vertex: People

Side: A and B has a call log

Right side: the total length of the call between A and B

Point right: A talk time of participation and

Between the apex is greater than 2 and communicate with each other, the total edge weight greater than a given threshold value K communication block for criminal groups; the maximum total vertex point right boss.


ps: In the undirected graph, if two vertices can reach each other (may be indirectly reachable through a given path), then the communication with said two vertices.

  • The maximum number of vertices should be> 2000 !!!

    This she did not pay attention, the result has been an error

    Because questions asked: call log N <= 1000,

    If every call is different and there are two dozen of the 2,000 people.

  • The number of output criminal groups, the name and number of the group leader for each group, lexicographical sorted by name.


Code

#include<iostream>
#include<string>
#include<map>
#include<queue>

using namespace std;

const int maxN=2010;//总人数 
const int INF=1000000000;//表示无效边
int G[maxN][maxN]; //邻接矩阵实现无向图
map<string ,int> nameMap;//人名与编号
map<int ,string> nameMap2;//编号与人名
map<int,int> vWeight;//点权
bool vis[maxN]; //访问数组
int N,K;//通话记录的数量,边权的阈值
//map<vector<int>,string> gangMap;
map<string,int> gangMap;//老大的名字 -> 犯罪团体人数

/*遍历一个连通分量*/
//u当前顶点编号,num 连通分量的人数,eWei总边权 ,leNo 老大编号
void DFS(int u,int& num,int& eWei,int& leNo) {
    vis[u]=true;
    num++;
    if(vWeight[u]>vWeight[leNo]) {//在遍历过程中,不断更新老大编号
        leNo=u;
    }

    for(int i=0; i<N; i++) { //遍历与u连通的点
        if(G[u][i]!=INF) {
            eWei+=G[u][i];
            if(vis[i]==false) {
                DFS(i,num,eWei,leNo);
            }
        }
    }


}
/*遍历整个图的连通分量*/
void DfsTraverse() {
    for(int u=0; u<N; u++) {
        if(vis[u]==false) {
            int num=0,eWei=0,leNo=-1;//连通分量的人数,总边权 ,老大编号
            DFS(u,num,eWei,leNo);

            if(num>2&&eWei>K) {
                gangMap.insert({nameMap2[leNo],num});
            }
        }
    }
}

int main() {
    /*初始化*/
    fill(G[0],G[0]+maxN*maxN,INF);
    fill(vis,vis+maxN,false);

    scanf("%d%d\n",&N,&K);
    int no=0;//人名编号
    for(int i=0; i<N; i++) {//插入边权和点权
        string n1,n2;
        int t;
        cin>>n1>>n2;
        scanf("%d",&t);

        if(nameMap.find(n1)==nameMap.end()) { //nameMap中无人名n1
            nameMap[n1]=no;
            nameMap2[no]=n1;
            no++;
        }
        if(nameMap.find(n2)==nameMap.end()) {
            nameMap[n2]=no;
            nameMap2[no]=n2;
            no++;
        }
        G[nameMap[n1]][nameMap[n2]]=t;//无向图边插两次 //是否要累加时间???
        G[nameMap[n2]][nameMap[n1]]==t;
        vWeight[nameMap[n1]]+=t;
        vWeight[nameMap[n2]]+=t;
    }

    DfsTraverse();

    cout<<gangMap.size()<<endl;
    for(auto x:gangMap){
        cout<<x.first<<" "<<x.second<<endl; 
    }

    return 0;
}


note

  • scanf string variables can not be directly input data, resize need to pre-allocate space; or directly with the char [].

    * Not recommended input string with scanf

    //错误(不会报错,但运行程序会有问题)
    string n1,n2;
    int t;
    scanf("%s %s %d\n",&n1,&n2,&t);
    //正确一
    string n1,n2;
    n1.resize(3); //需要预分配空间
    n2.resize(3); 
    int t;
    scanf("%s %s %d\n",&n1[0],&n2[0],&t);
    //正确二
    char n1[3],n2[3];
    int t;
    scanf("%s %s %d\n",&n1,&n2,&t);


  • scanf input data Note:

    • Such an operating result :( normal)
    scanf("%d%d\n",&N,&K);
    for(int i=0; i<N; i++) {
        string n1,n2;
        int t;
        cin>>n1>>n2;
        scanf("%d",&t);//最后没加\n
        ....
    }


    • Such an operating result :( error) need to resort to a character in order to continue
    scanf("%d%d\n",&N,&K);
    for(int i=0; i<N; i++) {
        string n1,n2;
        int t;
        cin>>n1>>n2;
        scanf("%d\n",&t);//最后加了\n
        ....
    }


  • Two-dimensional array initialization assignment

    • 这样写是将二维数组的第一个元素G[0][0]赋值为2,其他为0,不知道为什么会记成将数组全部元素赋值为2。。全部元素赋值用memset或fill
    int G[maxN][maxN]= {2};
    • 二维数组使用fill:

      注意不能写成 fill(G,G+maxN*maxN,INF)

      fill(G[0],G[0]+maxN*maxN,INF);

Guess you like

Origin www.cnblogs.com/musecho/p/12274442.html