BZOJ 1051: [HAOI2006]受欢迎的牛(SCC)

1051: [HAOI2006]受欢迎的牛

Time Limit: 10 Sec  Memory Limit: 162 MB
Submit: 8172  Solved: 4470
[Submit][Status][Discuss]

Description

  每一头牛的愿望就是变成一头最受欢迎的牛。现在有N头牛,给你M对整数(A,B),表示牛A认为牛B受欢迎。 这
种关系是具有传递性的,如果A认为B受欢迎,B认为C受欢迎,那么牛A也认为牛C受欢迎。你的任务是求出有多少头
牛被所有的牛认为是受欢迎的。

Input

  第一行两个数N,M。 接下来M行,每行两个数A,B,意思是A认为B是受欢迎的(给出的信息有可能重复,即有可
能出现多个A,B)

Output

  一个数,即有多少头牛被所有的牛认为是受欢迎的。

Sample Input

3 3
1 2
2 1
2 3

Sample Output

1

HINT

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

Source

 
[Submit][Status][Discuss]


HOME Back

题解:

强连通分量缩点;然后统计每一部分的出度,出度为零;出度为零的即为最受所有人欢迎的牛;(注意:只有有一个这样的“点”,如果有多个,则输出0)

参考代码:

 1  #include<bits/stdc++.h>
 2 #define N 10050
 3 using namespace std;
 4 struct EDGE{
 5     int next,to;
 6 }edge[N*20];
 7 int head[20*N],dfn[N],low[N];
 8 int du[N],id[N],all[N];
 9 bool insta[N];int cnt,tot,gg,n,m;
10 stack<int>s;
11 inline void add(int x,int y)
12 {
13     cnt++;
14     edge[cnt].to=y;
15     edge[cnt].next=head[x];
16     head[x]=cnt;
17 }
18 void in(int &read)
19 {
20     int x=0,f=1;char ch;
21     for(ch=getchar();(ch<'0'||ch>'9')&&ch!='-';ch=getchar());
22     if(ch=='-'){f=-1;ch=getchar();}
23     while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
24     read=x*f;//可以处理负数的读入优化
25 }
26     
27 void tarjan(int x)
28 {
29     dfn[x]=low[x]=++tot;
30     s.push(x);insta[x]=true;
31     for(int i=head[x];i;i=edge[i].next)
32     {
33         int u=edge[i].to;
34         if(!dfn[u])
35         {
36             tarjan(u);
37             low[x]=min(low[x],low[u]);
38         }
39         else if(insta[u])low[x]=min(low[x],dfn[u]);
40     }
41     int k;
42     if(low[x]==dfn[x])
43     {
44         ++gg;
45         do{
46             k=s.top();s.pop();
47             insta[k]=false;
48             id[k]=gg;all[gg]++;
49         }while(x!=k);
50     }
51 }
52 int main()
53 {
54     in(n);in(m);
55     int a,b;
56     for(register int i=1;i<=m;i++)
57     {
58         in(a);in(b);
59         add(a,b);
60     }
61     for(register int i=1;i<=n;i++)
62         if(!dfn[i])tarjan(i);
63     for(register int w=1;w<=n;w++)
64     {
65         for(int i=head[w];i;i=edge[i].next)
66         {
67             int u=edge[i].to;
68             if(id[w]!=id[u]) du[id[w]]++;
69         }
70     }
71     int tt=0;
72     for(register int i=1;i<=gg;i++)
73         if(!du[i])
74         {
75             if(tt){puts("0");return 0;}
76             tt=i;
77         }
78     printf("%d
",all[tt]);
79     return 0;
80 }
View Code
原文地址:https://www.cnblogs.com/csushl/p/10073545.html