BZOJ1051 [HAOI2006] 受欢迎的牛

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1051

Description

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

Input

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

Output

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

 

复习Tarjan模版,Tarjan后缩点,若有且只有一个出度为0的强联通分量则输出其大小,否则无解

因为缩点后的图是没有双向边的(如果有那就是一个强联通分量了)

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <algorithm>
 4 #include <cstring>
 5 #include <stack>
 6 #define rep(i,l,r) for(int i=l; i<=r; i++)
 7 #define clr(x,y) memset(x,y,sizeof(x))
 8 #define travel(x) for(int i=last[x]; i; i=edge[i].pre)
 9 using namespace std;
10 const int INF = 0x3f3f3f3f;
11 const int maxn = 10010;
12 struct Edge{
13     int pre,to;
14 }edge[50010];
15 int n,m,x,y,tot=0,ans,scc=0,dfsclock=0,last[maxn],dfn[maxn],low[maxn],belong[maxn],cnt[maxn];
16 bool isin[maxn],oud[maxn];
17 stack <int> s;
18 inline int read(){
19     int ans = 0, f = 1;
20     char c = getchar();
21     while (!isdigit(c)){
22         if (c == '-') f = -1;
23         c = getchar();
24     }
25     while (isdigit(c)){
26         ans = ans * 10 + c - '0';
27         c = getchar();
28     }
29     return ans * f;
30 }
31 inline void addedge(int x,int y){
32     edge[++tot].pre = last[x];
33     edge[tot].to = y;
34     last[x] = tot;
35 }
36 void tarjan(int x){
37     dfn[x] = low[x] = ++dfsclock;
38     isin[x] = 1; s.push(x);
39     travel(x){
40         if (!dfn[edge[i].to]){
41             tarjan(edge[i].to);
42             low[x] = min(low[x],low[edge[i].to]);
43         }
44         else if (isin[edge[i].to]) low[x] = min(low[x],dfn[edge[i].to]);
45     }
46     if (low[x] == dfn[x]){
47         scc++;
48         while (s.top() != x){
49             isin[s.top()] = 0;
50             belong[s.top()] = scc;
51             s.pop();
52             cnt[scc]++;
53         }
54         isin[x] = 0; belong[x] = scc; s.pop(); cnt[scc]++;
55     }
56 }
57 int main(){
58     n = read(); m = read();
59     rep(i,1,m) x = read(), y = read(), addedge(x,y);
60     clr(dfn,0); clr(cnt,0);
61     rep(i,1,n) if (!dfn[i]) tarjan(i);
62     clr(oud,0);
63     rep(now,1,n) travel(now) if (belong[now] != belong[edge[i].to]) oud[belong[now]] = 1;
64     ans = 0;
65     rep(i,1,scc) if (!oud[i]){
66         if (ans){ans = 0; break;}
67         ans = cnt[i];
68     }
69     printf("%d\n",ans);
70     return 0;
71 }
View Code

posted on 2015-12-01 17:38  ACMICPC  阅读(...)  评论(... 编辑 收藏

导航