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 }