#P2341 [HAOI2006]受欢迎的牛 题解

题目描述

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

牛都是自恋狂,每头奶牛总是喜欢自己的。奶牛之间的“喜欢”是可以传递的——如果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<bits/stdc++.h>
  2 #pragma comment(linker, "/STACK:102400000,102400000") //手动扩栈跑的快~~
  3 #define N 10050
  4 using namespace std;
  5 struct EDGE
  6 {
  7     int next,to;
  8 }edge[N*20];
  9 int head[20*N],dfn[N],low[N];
 10 int du[N],id[N],all[N];
 11 bool insta[N];
 12 int cnt,tot,gg,n,m;
 13 stack<int>s;
 14 void add(int x,int y)
 15 {
 16     cnt++;
 17     edge[cnt].to=y;
 18     edge[cnt].next=head[x];
 19     head[x]=cnt;
 20 }
 21 void in(int &read)
 22 {
 23     int x=0,f=1;
 24     char ch;
 25     for(ch=getchar();(ch<'0'||ch>'9')&&ch!='-';ch=getchar());
 26     if(ch=='-')
 27     {
 28         f=-1;
 29         ch=getchar();
 30     }
 31     while(ch>='0'&&ch<='9')
 32     {
 33         x=(x<<3)+(x<<1)+ch-'0';
 34         ch=getchar();
 35     }
 36     read=x*f;
 37     }
 38 void tarjan(int x)//targan模版 
 39 {
 40     dfn[x]=low[x]=++tot;
 41     s.push(x);insta[x]=true;
 42     for(int i=head[x];i;i=edge[i].next)
 43     {
 44         int u=edge[i].to;
 45         if(!dfn[u])
 46         {
 47             tarjan(u);
 48             low[x]=min(low[x],low[u]);
 49         }
 50         else if(insta[u])low[x]=min(low[x],dfn[u]);
 51     }
 52     int k;
 53     if(low[x]==dfn[x])
 54     {
 55         ++gg;
 56         while(x!=k)
 57         {
 58             k=s.top();s.pop();
 59             insta[k]=false;
 60             id[k]=gg;all[gg]++;
 61         }
 62     }
 63 }
 64 int main()
 65 {
 66     in(n);
 67     in(m);
 68     int a,b;
 69     for(int i=1;i<=m;i++)
 70     {
 71         in(a);
 72         in(b);
 73         add(a,b);
 74     }
 75     for(int i=1;i<=n;i++)
 76     {
 77         if(!dfn[i])
 78             tarjan(i);
 79     }
 80     for(int w=1;w<=n;w++)
 81     {
 82         for(int i=head[w];i;i=edge[i].next)
 83         {
 84             int u=edge[i].to;
 85             if(id[w]!=id[u])
 86             {
 87                 du[id[w]]++;
 88             }
 89         }
 90     }
 91     int tt=0;
 92     for(int i=1;i<=gg;i++)
 93     {
 94         if(!du[i])
 95         {
 96             if(tt)
 97             {
 98                 puts("0");
 99                 return 0;
100             }
101             tt=i;
102         }
103     }
104     printf("%d",all[tt]);
105     return 0;
106 }
View Code