算法笔记 PAT A1034 Head of a Gang (DFS遍历图)

就不放原题,直接给自己的算法和思路啦。
这道题对于我现在的水平来说,还是比较难的,所以就在看书的情况之下学习吧。
1.首先要解决的是,姓名和编号的对应关系:可以使用map <‘String’ int >建立字符串与整型的映射关系,或者是使用字符串hash的方法将字符串转化为整型,2.要获得每个人的权值,也就是和他相关的通话记录的时长之和,即求与某个点相连的边的边权之和 3.进行图的遍历,获得每个连通块的头目,成员个数,总边权。4.最后进行判断。如果值大于给定阈值,并且成员个数大于2,即存储下来。

#include<stdio.h>
#include<string.h>
//#include <stdbool.h>
#include <algorithm>
#include<queue>
using  namespace std;
const int maxn=2010;
const int INF=10000000;

map<int ,string> intToString;//编号-->姓名
map<string,int> stringToInt;//姓名-->编号
map<string ,int> Gang;//head->人数
int G[maxn][maxn]={0},weight[maxn]={0};//邻接矩阵G,点权weight
int n,k,numPerson=0;//边数n,下限k,总人数numPerson
bool vis[maxn]={false};

//DFS函数访问单个连通块,nowVist 为当前访问的编号
//head为头目,numMember 为成员编号,totalValue 为连通块的总边权

void DFS(int nowVisit,int& head,int& numMember,int&totalValue){
    numMember++;//成员人数加一
    vis(nowVisit)=true;//标记为已经访问过了
    if(weight[nowVisit]>weight[head]){
        head=nowVisit;//当前访问结点的点权大于头目的点权,则更新头目
    }
    for(int i=0;i<numPerson;i++){
        for(G(nowVisit)[i]>0){//如果从nowVisit 能到达i
            totalValue+=G[nowVisit][i];//连通块的总边权增加到该边权
            G[nowVisit][i]=G[i][nowVisit]=0;//删除这条边,防止回头
                if(vis[i]==false){//如果i未被访问,则递归访问i
                        DFS(I,head,numMember,totalValue);
                    
                }
        }
    }
}
//DFSTrave 函数遍历整个图,获取每个连通块的信息
void DFSTrave(){
    for(int i=0;i<numPerson;i++){
        if(vis[i]==false){
            int head=i,numMember,totalValue=0;//头目,成员数,总边权
            DFS(i,head,numMember,totalValue);
            if(numMember>2&&totalValue>k){//成员数大于2且总边权大于k
                //head 人数为numMember
                Gang[intToString[head]]=numMember;
            }
        }
    }
}
//change 函数返回姓名str对应的编号
int change(string str){
    if(stringToInt.find(str)!=stringToInt.end()){//如果str已经出现过
     return stringToInt[str];//返回编号
    }
    else{
        stringToInt[str]=numPerson;//str的编号是numPerson
        intToString[numPerson]=str;//numPerson 对应str
        return numPerson++;
    }
}

int main()
{
    int w;
    string str1,str2;
    cin>>n>>k;
    for(int i=0;i<n;i++){
        cin>>str1>>str2>>w;//输入边的两个端点和点权
        int id1=change(str1);
        int id2=change(str2);//两个转变
        weight[id1]+=w;
        weight[id2]+=w;
        G[id1][id2]+=w;
        G[id2][id1]+=w;
    }
    DFSTrave();//遍历整个图的所有连通块,获取gang的消息
    cout<<Gang.size()<<end1;//Gang的个数
    map<string,int>::iterator it;
    for(it=Gang.begin();it!=Gang.end();it++){
        //遍历所有的Gang
        cout<<it->first<<" "<<it->second<<end1;//输出信息
    }
    return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值