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

洛谷 P2341 [HAOI2006]受欢迎的牛 题解

时间:2017-10-11 12:59:54      阅读:204      评论:0      收藏:0      [点我收藏+]

标签:getchar   main   inline   之间   bre   get   set   说明   logs   

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

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

题目描述

每头奶牛都梦想成为牛棚里的明星。被所有奶牛喜欢的奶牛就是一头明星奶牛。所有奶

牛都是自恋狂,每头奶牛总是喜欢自己的。奶牛之间的“喜欢”是可以传递的——如果A喜

欢B,B喜欢C,那么A也喜欢C。牛栏里共有N 头奶牛,给定一些奶牛之间的爱慕关系,请你

算出有多少头奶牛可以当明星。

输入输出格式

输入格式:

? 第一行:两个用空格分开的整数:N和M

? 第二行到第M + 1行:每行两个用空格分开的整数:A和B,表示A喜欢B

输出格式:

? 第一行:单独一个整数,表示明星奶牛的数量

输入输出样例

输入样例#1:
3 3
1 2
2 1
2 3
输出样例#1:
1

说明

只有 3 号奶牛可以做明星

【数据范围】

10%的数据N<=20, M<=50

30%的数据N<=1000,M<=20000

70%的数据N<=5000,M<=50000

100%的数据N<=10000,M<=50000

 

Tarjan缩点  模板题

AC代码:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<stack> 
 6 //Tarjan
 7 const int MAXN = 500005;
 8 inline void read(int &x)
 9 {
10     char ch = getchar(),c = ch;x = 0;
11     while(ch < 0 || ch > 9) c = ch,ch = getchar();
12     while(ch <= 9 && ch >= 0) x = (x<<1)+(x<<3)+ch-0,ch = getchar();
13     if(c == -) x = -x;
14 }
15 
16 int head[MAXN],dfn[MAXN],low[MAXN];
17 //dfn:时间戳  low:子节点中开始时间最早的节点的开始时间。
18 int belong[MAXN],sum[MAXN],out[MAXN];
19 //belong[i]:i点属于哪一个强连通分量
20 //sum[i]:强连通分量i中的点数
21 //out[i]:强连通分量i的出度 
22 int cnt,dfn_cnt,part,n,m,f,t,ans,flag; 
23 inline int Min(int a,int b)
24 {return a<b?a:b;}
25 
26 struct Edge
27 {
28     int f,t,nxt;
29 }e[MAXN];
30 
31 inline void insert(int f,int t)
32 {
33     e[++cnt].f = f,e[cnt].t = t;
34     e[cnt].nxt = head[f],head[f] = cnt;
35 }
36 
37 std::stack <int> s;
38 
39 void Tarjan(int u)
40 {
41     s.push(u);
42     dfn[u] = low[u] = ++ dfn_cnt;
43     for(int i = head[u];i != -1;i = e[i].nxt)
44     {
45         int v = e[i].t;
46         if(!dfn[v]){
47             Tarjan(v);
48             low[u] = Min(low[u],low[v]);
49         }
50         else if(!belong[v])
51             low[u] = Min(low[u],dfn[v]);
52     }
53     //遍历一次之后dfn和low值仍相等,说明从u开始遍历到的节点都在一个强连通分量中 
54     if(dfn[u] == low[u])
55     {
56         ++ part;
57         while(!s.empty())
58         {
59             int x = s.top();
60             s.pop();
61             belong[x] = part;
62             sum[part] ++;
63             if(x == u) break;
64         }
65     }
66 }
67 
68 int main()
69 {
70     memset(head,-1,sizeof(head));
71     read(n),read(m);
72     for(int i = 1;i <= m;++ i)
73     {
74         read(f),read(t);
75         insert(f,t);
76     }
77     for(int i = 1;i <= n;++ i)
78         if(!dfn[i])
79             Tarjan(i);
80     for(int i = 1;i <= m;++ i)
81         if(belong[e[i].f] != belong[e[i].t])
82             out[belong[e[i].f]] ++;
83     //有且只有一个强连通分量的出度为0时,才存在"明星奶牛" 
84     for(int i = 1;i <= part;++ i)
85     {
86         if(!flag && !out[i]){
87             flag = 1;
88             ans = sum[i];
89         }
90         else if(flag && !out[i]){
91             ans = 0;
92             break;
93         }
94     }
95     printf("%d\n",ans);
96     return 0;
97 }

 

洛谷 P2341 [HAOI2006]受欢迎的牛 题解

标签:getchar   main   inline   之间   bre   get   set   说明   logs   

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

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