码迷,mamicode.com
首页 > 其他好文 > 详细

洛谷 P2835 刻录光盘 题解

时间:2017-10-11 20:21:17      阅读:172      评论:0      收藏:0      [点我收藏+]

标签:拷贝   题解   输入输出格式   计算   else   art   输入数据   一点   article   

此文为博主原创题解,转载时请通知博主,并把原文链接放在正文醒目位置。

题目链接:https://www.luogu.org/problem/show?pid=2835

题目描述

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

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

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

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

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

输入输出格式

输入格式:

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

输出格式:

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

输入输出样例

输入样例#1:
5
2 3 4 0
4 5 0
0
0
1 0
输出样例#1:
1


分析:
Tarjan缩点,然后记录每个强连通分量的入度。入度为0的点的数量就是最终答案。
数组要开大一点...边最多可以有接近40000条。
以及听说数据卡快读(很可能是数据出错了但是一直没改),改用scanf吧。

AC代码:
 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cmath>
 4 #include<cstring>
 5 #include<iostream>
 6 #include<stack>
 7 
 8 const int MAXN = 1005;
 9 
10 int n,f,t,cnt,dfn_cnt,part,ans;
11 int head[MAXN<<6],dfn[MAXN],low[MAXN];
12 int belong[MAXN],sum[MAXN],in[MAXN];
13 
14 struct Edge
15 {
16     int f,t,nxt;
17 }e[MAXN<<6];
18 
19 inline void insert(int f,int t)
20 {
21     e[++cnt].f = f,e[cnt].t = t;
22     e[cnt].nxt = head[f],head[f] = cnt;
23 }
24 
25 inline int Min(int a,int b)
26 {return a<b?a:b;}
27 
28 std::stack <int> s; 
29 
30 void Tarjan(int u)
31 {
32     s.push(u);
33     dfn_cnt ++;
34     dfn[u] = low[u] = dfn_cnt;
35     
36     for(int i = head[u];i;i = e[i].nxt)
37     {
38         int v = e[i].t;
39         if(!dfn[v]){
40             Tarjan(v);
41             low[u] = Min(low[u],low[v]);
42         }
43         
44         else if(!belong[v])
45             low[u] = Min(low[u],dfn[v]);
46     }
47     
48     if(dfn[u] == low[u])
49     {
50         ++ part;
51         while(!s.empty())
52         {
53             int x = s.top();
54             s.pop();
55             belong[x] = part;
56             sum[part] ++;
57             if(x == u) break;
58         }
59     }
60 }
61 
62 int main()
63 {
64     scanf("%d",&n);
65     for(int i = 1;i <= n;++ i)
66         while(1)
67         {
68             scanf("%d",&t);
69             if(!t) break;
70             insert(i,t);
71         }
72     for(int i = 1;i <= n;++ i)
73         if(!dfn[i])
74             Tarjan(i);
75     for(int i = 1;i <= cnt;++ i)
76     {
77         f = e[i].f,t = e[i].t;
78         if(belong[f] != belong[t])
79             in[belong[t]] ++;
80     }
81     for(int i = 1;i <= part;++ i)
82         if(!in[i]) ans ++;
83     printf("%d\n",ans);
84     return 0;
85 }

 

洛谷 P2835 刻录光盘 题解

标签:拷贝   题解   输入输出格式   计算   else   art   输入数据   一点   article   

原文地址:http://www.cnblogs.com/shingen/p/7652338.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!