E 通知小弟

 这个我啥都不知道,一直调试了,5天

多组输入直接挂init 和 slove

然后强连通组个数 scc_cnt   是哪个组的 scc[]     能通到的ind[]

代码从大佬哪里扒过来的


题目描述

        在战争时期,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<string.h>
using namespace std;
const int maxn = 1e6+5;
#define f(i,l,r) for(int i=l;i<=r;i++)
#define g(i,l,r) for(int i=l;i>=r;i--)


int n,m ,x,y;
int ha[maxn],ok[maxn];
struct edge{
	int v,nxt;
};
edge e[maxn];
int dfn[maxn],low[maxn],cnt,tot,indexx,stack[maxn];
int heads[maxn],vis[maxn];
int scc[maxn],scc_cnt,ind[maxn],ans;
void init()
{
	ans = scc_cnt = cnt=tot=indexx=0;
	memset(ha,0,sizeof(ha));
	memset(ok,0,sizeof(ok));
	memset(e,0,sizeof(e));
	memset(dfn,0,sizeof(dfn));
	memset(low,0,sizeof(low));
	memset(stack,0,sizeof(stack)); 
	memset(heads,0,sizeof(heads)); 
	memset(vis,0,sizeof(vis)); 
	memset(scc,0,sizeof(scc)); 
	memset(ind,0,sizeof(ind));
}
void add(int x,int y)
{
	e[++cnt].nxt = heads[x];
	e[cnt].v = y;
	heads[x]=cnt; 
}
void tarjan(int x)
{
	dfn[x]=low[x]=++tot;
	stack[++indexx]=x;vis[x]=1;
	for(int i = heads[x];i!=0;i=e[i].nxt) 
	{
		int t = e[i].v;
		if(!dfn[t])
		{
			tarjan(t);
			low[x]=min(low[x],low[t]);
		}
		else if(vis[t])
		{
			low[x]=min(low[x],dfn[t]);
		}
	}
	if(dfn[x]==low[x])
	{
		scc_cnt++;
		while(1)
		{
			int t = stack[indexx--];
			scc[t]=scc_cnt;
			vis[t]=0;
			if(x==t)break;
		}
	}
}
void slove()
{
	f(i,1,n)if(!dfn[i])tarjan(i);
	f(i,1,n)
		for(int j =heads[i];j;j=e[j].nxt )
		 if(scc[i]!=scc[e[j].v])
		 	ind[scc[e[j].v]]++;
	 
	
	f(i,1,scc_cnt)
	 	if(ind[i]==0)
	 		ans++;
	 if(ans>m)
	 {
	 	cout<<-1<<endl;
	 	return ;
	 }
	 f(i,1,n)
	 {
		if(ind[scc[i]]==0 && ha[i]==1)
		{
			ok[scc[i]]=1;
		}	 	
	 }	 
	 f(i,1,scc_cnt)
	{
		if(ind[i]==0 && !ok[i])
		{
			cout<<-1<<endl;
			return ;
		}	  
	}
	cout<<ans<<endl;
	return ;

}


int main()
{
	//freopen("in","r",stdin);
	while(cin>>n>>m)
	{
		init();
		f(i,1,m)
		{
			cin>>x;
			ha[x]=1;	
		}
		
		f(i,1,n)
		{	
			cin>>x;
			f(j,1,x)
			{
				cin>>y;
				add(i,y);					
			}
		}
		slove(); 
	}
	return 0;

}

发布了59 篇原创文章 · 获赞 3 · 访问量 1万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章