vijos 1022 Victoria的舞会2
描述
Victoria是一位颇有成就的艺术家,他因油画作品《我爱北京天安门》闻名于世界。现在,他为了报答帮助他的同行们,准备开一个舞会。
Victoria准备邀请n个已经确定的人,可是问题来了:
这n个人每一个人都有一个小花名册,名册里面写着他所愿意交流的人的名字。比如说在A的人名单里写了B,那么表示A愿意与B交流;但是B的名单里不见的有A,也就是说B不见的想与A交流。但是如果A愿意与B交流,B愿意与C交流,那么A一定愿意与C交流。也就是说交流有传递性。
Victoria觉得需要将这n个人分为m组,要求每一组的任何一人都愿意与组内其他人交流。并求出一种方案以确定m的最小值是多少。
注意:自己的名单里面不会有自己的名字。
格式
输入格式
第一行一个数n。接下来n行,每i+1行表示编号为i的人的小花名册名单,名单以0结束。1<=n<=200。
输出格式
一个数,m。
样例1
样例输入1
18
0
18 0
0
0
11 0
0
0
0
0
0
5 0
0
0
0
0
0
0
2 0
样例输出1
16
限制
各个测试点1s
来源
Vivian Snow
a的名单里有b,就连一条a向b的单向边,这样图中的联通块就是可以在一起的人了。。。
可以topsort+并查集乱搞就像15年noip day1 T2一样,也可以直接用tarjan
1 // 2 // 1022.cpp 3 // code 4 // 5 // Created by 张淇 on 2017/9/30. 6 // Copyright © 2017年 张淇. All rights reserved. 7 // 8 #include<iostream> 9 #define maxn 2010 10 using namespace std; 11 struct edge{ 12 int next,go; 13 }e[2010]; 14 int head[maxn],tot; 15 int cnt,ti,n,m,top; 16 int low[2000],dfn[2000],scc[2000],sta[2000],s[2000]; 17 void insert(int u,int v){ 18 e[++tot].go=v;e[tot].next=head[u];head[u]=tot; 19 } 20 void dfs(int x){ 21 int y; 22 low[x]=dfn[x]=++ti;sta[++top]=x; 23 for(int i=head[x];i;i=e[i].next) 24 if(!dfn[y=e[i].go]){ 25 dfs(y); 26 low[x]=min(low[x],low[y]); 27 } 28 else if(!scc[y])low[x]=min(low[x],dfn[y]); 29 if(low[x]==dfn[x]){ 30 //cout<<x<<endl; 31 cnt++; 32 while(1){ 33 scc[y=sta[top--]]=cnt;s[cnt]++; 34 if(y==x)break; 35 } 36 } 37 } 38 void tarjan(){ 39 for(int i=1;i<=n;i++) 40 if(!dfn[i]) 41 dfs(i); 42 } 43 int read(){ 44 int x=0,f=1;char ch=getchar(); 45 while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} 46 while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} 47 return f*x; 48 } 49 int main(){ 50 freopen("input.txt","r",stdin); 51 n=read(); 52 for(int i=1;i<=n;i++){ 53 int x=read(); 54 while(x!=0){ 55 insert(i,x); 56 x=read(); 57 } 58 } 59 tarjan(); 60 cout<<cnt<<'\n'; 61 }