犯罪团伙

32 篇文章 1 订阅
8 篇文章 1 订阅

一、原题

犯罪团伙(gang.cpp)

题目描述

警察抓到了n个罪犯,警察根据经验知道他们属于不同的犯罪团伙,却不能判断有多少个团伙,但通过警察的审讯,知道其中的一些罪犯之间相互认识,已知同一犯罪团伙的成员之间直接或间接认识。
有可能一个犯罪团伙只有一个人。请你根据已知罪犯之间的关系,确定犯罪团伙的数量。已知罪犯的编号从1至n。

输入

第1行:n(<=500,罪犯数量),m(<50000,关系数量)
以下m行:每行两个数:i 和j,中间一个空格隔开,表示罪犯i和罪犯j相互认识。

输出

第1行:一个整数,犯罪团伙的数量。

样例输入

11 8
1 2
4 3
5 4
1 3
5 6
7 10
5 10
8 9

样例输出

3

概念图

犯罪团伙概念图


二、分析

这道题首先我一看,就需要用到邻接表,所以,我们先定义两个临时变量来存储能够相互连通的数。

bool a[502][502];//定义bool类型的邻接表
for(int i=1;i<=m;i++){//建立邻接表
    int x,y;//临时变量
    cin>>x>>y;//读入
    a[x][y]=a[y][x]=1;//标记以建立邻接表
}

然后我们就要就要搜索了,首先,我们把搜索函数的函数搭建好,这个搜索函数主要是删点,顺便把用过的点记录一下,好为没有与其它点连通的点计数,为单独的犯罪团伙。

void dfs(int x){//删除点的函数
    for(int i=1;i<=n;i++){
        if(a[x][i]){//如果x与i联通
            a[x][i]=a[i][x]=0;//在邻接表中删掉两个点的联通
            p[x]=p[i]=1;//记录已被记录的点
            dfs(i);//继续搜索
        }
    }
}

然后,用for循环,把一个一个的调用函数一下,同上,记录点已经被使用过。

for(int i=1;i<=n;i++)
    for(int j=1;j<=n;j++)
        if(a[i][j]){
            p[i]=p[j]=1;//记录点已被使用过
            dfs(i);//搜索以删点
            ans++;//答案+1
        }

最后,我们愉快的把那些不与任何点连通的点单独算作一个犯罪团伙就行啦。

for(int i=1;i<=n;i++)
        if(!p[i])//不与任何点连通的点
            ans++;//答案+1

输出答案,这道题就是那么的简单。完整的代码如下:)


三、源代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<time.h>
#include<algorithm>
#include<queue>
using namespace std;
bool a[502][502],p[502];
int b=1,t,n,f,ans,m;
void fre(){//文件的读入输出
    freopen("gang.in","r",stdin);
    freopen("gang.out","w",stdout);
}
void dfs(int x){//删除点的函数
    for(int i=1;i<=n;i++){
        if(a[x][i]){//如果x与i联通
            a[x][i]=a[i][x]=0;//在邻接表中删掉两个点的联通
            p[x]=p[i]=1;//记录已被记录的点
            dfs(i);//继续搜索
        }
    }
}
int main()
{
    //fre();//文件的输入输出
    cin>>n>>m;
    for(int i=1;i<=m;i++){//建立邻接表
        int x,y;//临时变量
        cin>>x>>y;//读入
        a[x][y]=a[y][x]=1;//标记以建立邻接表
    }
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
            if(a[i][j]){
                p[i]=p[j]=1;//记录点已被使用过
                dfs(i);//搜索以删点
                ans++;//答案+1
            }
    for(int i=1;i<=n;i++)
        if(!p[i])//不与任何点连通的点
            ans++;//答案+1
    cout<<ans;
}
  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值