版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/imotolove/article/details/80637074
链接:https://www.nowcoder.com/acm/contest/76/E
来源:牛客网
题目描述
在战争时期,A国派出了许多间谍到其他国家去收集情报。因为间谍需要隐秘自己的身份,所以他们之间只是单向联系。所以,某个间谍只能单向联系到一部分的间谍。同时,间谍也不知道跟他联系的是谁。
HA是间谍们的老大,但他也只能联系到部分的间谍。HA现在有一项命令有告诉所有的间谍。HA想要知道他至少要告诉多少个他能联系上的间谍才能通知到所有的间谍。
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。
这题为有向图,有主次,所以可以使用并查集实现,每一次传递消息就是一次路径压缩,只用找出那些孤立点再与ha比较就行
#include<bits/stdc++.h>
using namespace std;
int f[501],n,m,l;
int can[501];
int findset(int x)
{
return x==f[x]?x:findset(f[x]);
}
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
f[i]=i;
for(int i=1;i<=m;i++)
{
cin>>l;
can[l]=1;
}
for(int i=1;i<=n;i++)
{
int a,k;
cin>>a;
int aa=findset(i),bb;
while(a--)
{
cin>>k;
bb=findset(k);
if(aa!=bb)
f[k]=i;
}
}
int flag=0,ans=0;
for(int i=1;i<=n;i++)
{
if(f[i]==i)
{
if(!can[i])
{
flag=1;
break;
}
ans++;
}
}
if(flag==0)
cout<<ans<<endl;
else
cout<<-1<<endl;
return 0;
}