【题目描述】
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 #include <cstdio> 2 #include <iostream> 3 #include <cstring> 4 #include <algorithm> 5 #include <queue> 6 #include <cctype> 7 #include <cmath> 8 #include <time.h> 9 10 using namespace std; 11 12 #define ms(a,b) memset(a,b,sizeof(a)) 13 14 const int maxn=210; 15 const int maxm=50010; 16 17 struct Edge{ 18 int to,next; 19 }edge[maxm<<1]; 20 21 int dfn[maxn],vis[maxn],low[maxn],stack[maxn],belong[maxn]; 22 int head[maxm]; 23 int nedge,n,top,sum,dep; 24 25 inline int read() 26 { 27 int X=0,w=0; char ch=0; 28 while(!isdigit(ch)) {w|=ch=='-';ch=getchar();} 29 while(isdigit(ch)) X=(X<<3)+(X<<1)+(ch^48),ch=getchar(); 30 return w?-X:X; 31 } 32 33 void tarjan(int u) 34 { 35 dfn[u]=low[u]=++dep; 36 stack[top++]=u; 37 vis[u]=1; 38 for (int i=head[u];i!=-1;i=edge[i].next) 39 { 40 int v=edge[i].to; 41 if (!dfn[v]) 42 { 43 tarjan(v); 44 low[u]=min(low[u],low[v]); 45 } 46 else 47 { 48 if (vis[v]) low[u]=min(low[u],dfn[v]); 49 } 50 } 51 int j; 52 if (low[u]==dfn[u]) 53 { 54 ++sum; 55 do 56 { 57 j=stack[--top]; 58 belong[j]=sum; 59 vis[j]=0; 60 } 61 while (u!=j); 62 } 63 } 64 65 void add_edge(int a,int b) 66 { 67 edge[nedge]=(Edge){b,head[a]}; head[a]=nedge++; 68 } 69 70 int main() 71 { 72 ms(head,-1); 73 n=read(); 74 for (int i=1;i<=n;i++) 75 { 76 while (1) 77 { 78 int x=read(); 79 if(x==0) break; 80 add_edge(i,x); 81 } 82 } 83 for (int i=1;i<=n;i++) 84 { 85 if (!dfn[i]) tarjan(i); 86 } 87 printf("%d\n",sum); 88 return 0; 89 }