洛谷 P2341 [HAOI2006]受欢迎的牛 题解
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了洛谷 P2341 [HAOI2006]受欢迎的牛 题解相关的知识,希望对你有一定的参考价值。
此文为博主原创题解,转载时请通知博主,并把原文链接放在正文醒目位置。
题目链接: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]受欢迎的牛 题解的主要内容,如果未能解决你的问题,请参考以下文章
POJ——T2186 Popular Cows || 洛谷——P2341 [HAOI2006]受欢迎的牛
洛谷 P2341 BZOJ 1051 [HAOI2006]受欢迎的牛