列表

详情


NC15120. 通知小弟

描述

        在战争时期,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

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++(g++ 7.5.0) 解法, 执行用时: 55ms, 内存消耗: 424K, 提交时间: 2022-09-20 20:11:49

#include<bits/stdc++.h>
using namespace std;
int fa[501],n,m,l;
int can[501];
int find(int x)
{
    if (fa[x] == x) return x;
    return find(fa[x]);
}
int main()
{
    cin>>n>>m;
    for(int i=1;i<=n;i++)
        fa[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=find(i),bb;
        while(a--)
        {
            cin>>k;
            bb=find(k);
            if(aa!=bb)
                fa[k]=i;
        }
    }
    int flag=0,ans=0;
    for(int i=1;i<=n;i++)
    {
        if(fa[i]==i)
        {
            if(!can[i])
            {
                flag=1;
                break;
            }
            ans++;
        }
    }
    if(flag==0)
    cout<<ans<<endl;
    else
    cout<<-1<<endl;
    return 0;
}

C++14(g++5.4) 解法, 执行用时: 64ms, 内存消耗: 2348K, 提交时间: 2020-05-23 11:33:36

#include<iostream>
#include<algorithm>
#include<stack>
#include<vector>

using namespace std;

const int N = 1000;

int n,m;
vector<int> v[N];
int num[N];
int ans;
int rul[N];
int vis[N];

void dfs(int x,int y)
{
	vis[x] = 1;
	for(int i=0; i<v[x].size(); i++)
	{
		int a = v[x][i];
		if(!vis[a]) dfs(a,y);
		else if(a != y && rul[a]) 
		{
			rul[a] = 1;
			ans--;
		}
	}
}

int main()
{
	cin>>n>>m;
	for(int i=0; i<m; i++) cin>>num[i];
	for(int i=1; i<=n; i++)
	{
		int a;
		cin>>a;
		for(int j=0; j<a; j++)
		{
			int b;
			cin>>b;
			v[i].push_back(b);
		}
	}
	for(int i=0; i<m; i++)
	{
		int a = num[i];
		if(!vis[a]) 
		{
			rul[a] = 1;
			ans++;
			dfs(a,a);
		}
	}
	for(int i=1; i<=n; i++) 
		if(!vis[i]) 
		{
			puts("-1");
			return 0;
		}
	cout<<ans;
	return 0;
}

C++11(clang++ 3.9) 解法, 执行用时: 33ms, 内存消耗: 1292K, 提交时间: 2020-03-26 23:30:37

#include<bits/stdc++.h>
#define ri register int
#define maxn 510
using namespace std;
int a[maxn],n,m,k,l,r,ans;
bool can[maxn];
int find(int n)
{
	if(n==a[n])
	return n;
	else
	return find(a[n]);
}
int main()
{
	ans=0;
	scanf("%d%d",&n,&m);
	for(ri i=1;i<=n;i++)
	{
		can[i]=false;
		a[i]=i;
	}
	for(ri i=1;i<=m;i++)
	{
		scanf("%d",&k);
		can[k]=true;
	}
	for(ri i=1;i<=n;i++)
	{
		scanf("%d",&l);
		int xl=find(i),xr;
		while(l--)
		{
			scanf("%d",&r);
			xr=find(r);
			if(xl!=xr)
			a[r]=i;
		}
	}
	bool f=false;
	for(int i=1;i<=n;i++)
	if(a[i]==i)
	{
		if(!can[i])
		{
			f=true;
			break;
		}
		ans++;
	}
	if(f==false)
	printf("%d\n",ans);
	else
	printf("-1\n");
	return 0;
}

上一题