题目背景
本题测试数据已修复。
题目描述
每头奶牛都梦想成为牛棚里的明星。被所有奶牛喜欢的奶牛就是一头明星奶牛。所有奶
牛都是自恋狂,每头奶牛总是喜欢自己的。奶牛之间的“喜欢”是可以传递的——如果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
解题思路:题目意思 找被所有牛都喜欢的牛的个数 先缩点然后找出度为0的点
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 #include <vector> 5 #include <algorithm> 6 #include <stack> 7 using namespace std; 8 int n,m,tot=0,cnt; 9 const int maxn=5e4+5; 10 vector<int> G[maxn]; 11 stack<int> sta; 12 int dfn[maxn],low[maxn],vis[maxn],save[maxn],dis[maxn],out[maxn],x[maxn],y[maxn]; 13 14 void tarjan(int ee){ 15 dfn[ee]=low[ee]=++tot; 16 vis[ee]=1;sta.push(ee); 17 for(int i=0;i<G[ee].size();i++){ 18 int u=G[ee][i]; 19 if(dfn[u]==0){ 20 tarjan(u); 21 low[ee]=min(low[ee],low[u]); 22 }else if(vis[u]){ 23 low[ee]=min(low[ee],dfn[u]); 24 } 25 } 26 if(dfn[ee]==low[ee]){ 27 cnt++; 28 while(!sta.empty()){ 29 int top=sta.top(); 30 sta.pop(); 31 vis[top]=0; 32 dis[cnt]++; ///这个强连通分量里面有多少个值 33 save[top]=cnt; ///这个节点是属于哪个强连通分量的 34 if(top==ee) break; 35 } 36 } 37 } 38 39 int main(){ 40 scanf("%d%d",&n,&m); 41 for(int i=1;i<=m;i++){ 42 scanf("%d%d",&x[i],&y[i]); 43 G[x[i]].push_back(y[i]); 44 } 45 for(int i=1;i<=n;i++){ 46 if(dfn[i]==0) tarjan(i); 47 } 48 for(int i=1;i<=m;i++){ 49 if(save[x[i]]!=save[y[i]]) out[save[x[i]]]++; ///这个强连通分量的出度为多少 50 } 51 int flag=0,res; 52 for(int i=1;i<=cnt;i++){ ///cnt 强连通分量的数量 53 if(out[i]==0){ 54 flag++;res=dis[i]; 55 } 56 } 57 printf("%d ",flag==1?res:0); 58 return 0; 59 }