[最短路-Floyd][并查集]SSL P2344 刻录光盘

 

Description

在PJOI2010夏令营快要结束的时候,很多营员提出来要把整个夏令营期间的资料刻录成一张光盘给大家,以便大家回去后继续学习。组委会觉得这个主意不错!可是组委会一时没有足够的空光盘,没法保证每个人都能拿到刻录上资料的光盘,又来不及去买了,怎么办呢? 

组委会把这个难题交给了DYJ,DYJ分析了一下所有营员的地域关系,发现有些营员是一个城市的,其实他们只需要一张就可以了,因为一个人呢拿到光盘以后,其他人可以拿着U盘之类的东西去拷贝啊! 

可是DYJ调查后发现,有些营员并不是那么合作,他们愿意某一些人到他那儿拷贝资料,当然也可能不愿意让另外一些人到他那儿拷贝资料,这与我们PJOI宣扬的团队合作精神格格不入! 

现在假设总共有N个营员(2<=N<=200),每个营员的编号为1~N。DJY给每个人发了一张调查表,让每个营员填上自己愿意让哪些人到他那儿拷贝资料。当然,如果A愿意把资料拷贝给B,而B又愿意把资料拷贝给C,则一旦A获得了资料,则B、C也会获得资料。 

现在请你编写一个程序,根据回收上来的调查表,帮助DZY计算出组委会至少要刻录多少张光盘,才能保证所有营员回去后都能得到夏令营资料?

Input

先是一个数N,接下来N行,分别表示各个营员愿意把自己获得的资料拷贝给其他哪些营员。即输入数据的第N+1行表示第i个营员愿意把资料拷贝给那些营员编号,以一个0结束。如果一个营员不愿意拷贝资料给任何人,则相应的行只有1个0,一行中的若干数之间用一个空格隔开。

Output

一个正整数,表示最少要刻录的光盘数。

Sample Input

 

5
2 4 3 0
4 5 0
0
0
1 0

 

Sample Output

 

1

 

题解

  • 题目其实就是让我们求有多少个联通块
  • 那么其实我们将给出的边定为true
  • 跑一遍Floyd,可以将可以达到的点全部跑出来
  • 然后,将这些边打进并查集
  • 最后求有多少个并查集

代码

 1 #include<cstdio>
 2 #include<iostream>
 3 using namespace std;
 4 int n,ans,f[210],v[210][210],a[210];
 5 void bing(int x,int y)
 6 {
 7     while (x!=f[x]) x=f[x];
 8     f[y]=x;
 9 }
10 int getfather(int x)
11 {
12     while (x!=f[x]) x=f[x];
13     return x;
14 }
15 int main()
16 {
17     scanf("%d",&n);
18     for (int i=1;i<=n;i++) f[i]=i;
19     for (int i=1;i<=n;i++)
20     {
21         int x;
22         scanf("%d",&x);
23         while (x!=0)
24         {
25             v[i][x]=true;
26             scanf("%d",&x);
27         }
28     }
29     for (int k=1;k<=n;k++)
30         for (int i=1;i<=n;i++)
31             for (int j=1;j<=n;j++)
32                 v[i][j]=v[i][j]||v[i][k]&&v[k][j];
33     for (int i=1;i<=n;i++)
34         for (int j=1;j<=n;j++)
35             if (v[i][j])
36                 bing(i,j);
37     for (int i=1;i<=n;i++) a[getfather(i)]=1;
38     for (int i=1;i<=n;i++) if (a[i]==1) ans++;
39     printf("%d",ans);
40     return 0;
41 }

 

posted @ 2018-03-15 16:43  BEYang_Z  阅读(261)  评论(0编辑  收藏  举报