链接: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;
}