PATA 1034 Head of a Gang

在这里插入图片描述
在这里插入图片描述

栽的坑记录一下
1.通话记录一共不超过1000,那么最多有多少人呢?2000!!!
2.

//给一个顶点DFS
void DFS(int nowMember,int &gangNum,int &head,int &totalTime){
    isTraver[nowMember]=true;
    gangNum++;
    if(weight[nowMember]>weight[head])
        head=nowMember;
    for(int i=0;i<numPerson;i++){
        if(G[nowMember][i]>0&&!isTraver[i]){
            totalTime+=G[nowMember][i];
            G[nowMember][i]=G[i][nowMember]=0;//避免多算
            DFS(i,gangNum,head,totalTime);
        }
    }
}

如果这样写会有什么问题呢?
当前结点访问完之后我们访问它的邻接顶点,访问的条件如果写成是

if(G[nowMember][i]>0&&!isTraver[i])

意思就是这两个顶点之间有关系,并且邻接的顶点没有被访问过,这样我们才把这条边权加到总的权值上,之后DFS。我们考虑一下下面(带圈)这种情况
在这里插入图片描述
走过的路线为红色部分,我们走到D了,B已经被访问过了,我们这时候肯定不能再对B进行DFS了,但是BD这条边执行我们的代码是不会加上去的,因此我们DFS和加边权应该分别执行。

代码如下

for(int i=0;i<numPerson;i++){
        if(G[nowMember][i]>0){
            totalTime+=G[nowMember][i];
            G[nowMember][i]=G[i][nowMember]=0;//避免多算
            if(!isTraver[i])
                DFS(i,gangNum,head,totalTime);
        }
    }

3.用迭代器循环的时候it<type.end()是不对的,结束条件应该是it!=type,end(),其中type为容器类型

#include <iostream>
#include <map>
#include <string>
using namespace std;

const int Maxn=2010;

int G[Maxn][Maxn]={0};//电话记录
bool isTraver[Maxn]={false};//是否被访问过
int weight[Maxn]={0};//每个人的相关的权值

//输入
int N,K;

map<string,int> strToint;
map<int,string> intTostr;
map<string,int> nameTonum;//每个头目对应的成员数量

int numPerson=0;//人数

//名字转编号
int change(string str){
    if(strToint.find(str)!=strToint.end()){//这个名字已经出现过了
        return strToint[str];
    }
    else{
        strToint[str]=numPerson;
        intTostr[numPerson]=str;
        return numPerson++;
    }
}

//给一个顶点DFS
void DFS(int nowMember,int &gangNum,int &head,int &totalTime){
    isTraver[nowMember]=true;
    gangNum++;
    if(weight[nowMember]>weight[head])
        head=nowMember;
    for(int i=0;i<numPerson;i++){
        if(G[nowMember][i]>0){
            totalTime+=G[nowMember][i];
            G[nowMember][i]=G[i][nowMember]=0;//避免多算
            if(!isTraver[i])
                DFS(i,gangNum,head,totalTime);
        }
    }
}

void dfsTraver(){
    for(int i=0;i<numPerson;i++){
        //帮派人数,头目,总时间
        int gangNum=0,head=i,totalTime=0;
        if(!isTraver[i]){
            DFS(i,gangNum,head,totalTime);
            if(gangNum>2&&totalTime>K)
                nameTonum[intTostr[head]]=gangNum;
        }
    }
}

int main()
{
    string str1,str2;
    cin>>N>>K;
    for(int i=0;i<N;i++){
        int id1,id2,time;
        cin>>str1>>str2;
        id1=change(str1);
        id2=change(str2);
        cin>>time;
        G[id1][id2]+=time,weight[id1]+=time;
        G[id2][id1]+=time,weight[id2]+=time;
    }

    dfsTraver();
    cout<<nameTonum.size()<<endl;
    for(map<string,int>::iterator it=nameTonum.begin();it!=nameTonum.end();it++)
        cout<<it->first<<" "<<it->second<<endl;

    return 0;
}

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值