标签:拷贝 题解 输入输出格式 计算 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,一行中的若干数之间用一个空格隔开。
输出格式:一个正整数,表示最少要刻录的光盘数。
5 2 3 4 0 4 5 0 0 0 1 0
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 }
标签:拷贝 题解 输入输出格式 计算 else art 输入数据 一点 article
原文地址:http://www.cnblogs.com/shingen/p/7652338.html