2018年全国多校算法寒假训练营练习比赛(第四场) - E - 通知小弟(BFS)

本文介绍了一个关于间谍网络的通知算法问题,通过构建图模型,使用广度优先搜索(BFS)来确定最少通知间谍数量,确保消息能够传递给每一个成员。文章详细解释了算法流程,并提供了一段完整的C++代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

链接:https://www.nowcoder.com/acm/contest/76/E
来源:牛客网

题目描述 
        在战争时期,A国派出了许多间谍到其他国家去收集情报。因为间谍需要隐秘自己的身份,所以他们之间只是单向联系。所以,某个间谍只能单向联系到一部分的间谍。同时,间谍也不知道跟他联系的是谁。
HA是间谍们的老大,但他也只能联系到部分的间谍。HA现在有一项命令有告诉所有的间谍。HA想要知道他至少要告诉多少个他能联系上的间谍才能通知到所有的间谍。
输入描述:
有多个测试数据。
对于每个测试数据:
第一行为一个整数n,m(0<n,m<=500)代表间谍的数量和HA能通知到的间谍的数量(间谍的编号为1-n);
第二行为m个用空格隔开的整数xi,代表HA能通知到的间谍的编号;
第三行到第n+2行,每一行第一个整数ai(0<=ai<n)表示第i-2个间谍能单向联系到的间谍数。之后有ai个用空格隔开的整数,表示间谍i-2能单向联系到的间谍的编号。
输出描述:
输出一行,此行中有一个整数,代表HA至少需要联系的间谍数。如果HA不能通知到所有间谍,输出-1。
示例1
输入

3 2
1 2
1 2
1 1
0
输出

-1
示例2
输入

3 1
1
2 2 3
0
0
输出

1

数据范围较小,所以直接来搜就行了

先找出哪些老大直接可以通知的小弟不能被其他老大可以直接通知的小弟通知

然后再判断老大直接可以通知的小弟能否通知到所有的小弟

如果可以,剩下的只能被老大通知的小弟即为答案


#include <iostream>
#include <stdio.h>
#include <string.h>
#include <queue>
using namespace std;
const int N = 5e2 + 10;
int n,m,x,y,z,a[N],b[N],mp[N][N],sz[N],vis[N];
int ans,cnt;
void bfs(int s){
    queue<int> q; q.push(s); vis[s] = 1;
    while(!q.empty()){
        s = q.front(); q.pop(); cnt++;
        for(int i=0;i<sz[s];i++){
            int nt = mp[s][i];
            if(vis[nt]) continue;
            q.push(nt); b[nt] = 0; vis[nt] = 1;
        }
    }
}
int main()
{
    while(scanf("%d%d",&n,&m)!=EOF){
        memset(vis,0,sizeof vis);
        memset(b,0,sizeof b);
        for(int i=0;i<m;i++) {
            scanf("%d",&x);
            a[i] = x; b[x] = 1;
        }
        for(int i=1;i<=n;i++) {
            scanf("%d",&sz[i]);
            for(int j=0;j<sz[i];j++){
                scanf("%d",&x); mp[i][j] = x;
            }
        }
        for(int i=0;i<m;i++){
            if(b[a[i]]) {
                memset(vis,0,sizeof vis);
                bfs(a[i]);
            }
        }
        ans = cnt = 0;
        memset(vis,0,sizeof vis);
        for(int i=0;i<m;i++){
            if(b[a[i]]){
                ans++;
                bfs(a[i]);
            }
        }
        printf("%d\n",cnt<n?-1:ans);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值