舞会

【题目描述】

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 }

猜你喜欢

转载自www.cnblogs.com/Dawn-Star/p/9332820.html