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萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章