[HAOI2006]受欢迎的牛
1051: [HAOI2006]受欢迎的牛
时间限制: 10 Sec 内存限制: 162 MB提交: 4406 解决: 2336
题目描述
每一头牛的愿望就是变成一头最受欢迎的牛。现在有N头牛,给你M对整数(A,B),表示牛A认为牛B受欢迎。 这
种关系是具有传递性的,如果A认为B受欢迎,B认为C受欢迎,那么牛A也认为牛C受欢迎。你的任务是求出有多少头
牛被所有的牛认为是受欢迎的。
输入
第一行两个数N,M。 接下来M行,每行两个数A,B,意思是A认为B是受欢迎的(给出的信息有可能重复,即有可
能出现多个A,B)
输出
一个数,即有多少头牛被所有的牛认为是受欢迎的。
样例输入
3 3
1 2
2 1
2 3
1 2
2 1
2 3
样例输出
1
提示
100%的数据N<=10000,M<=50000
题解:
Tarjan缩图, 如果有两个及两个以上出度为0的就输出0,排除以上情况输出出度为0的联通块中牛的个数。
#include <iostream> #define MAX 10001 using namespace std; struct node { int x, y, next; }road[50001]; int N, M, t, top, cnt, rd, dfn[MAX], stack[MAX], low[MAX], belong[MAX], num[MAX], first[MAX], out[MAX]; bool instack[MAX] = {false}; void Read() { cin >> N >> M; for(int i = 1; i <= M; ++i) { int x, y; cin >> x >> y; rd++; road[rd].x = x; road[rd].y = y; road[rd].next = first[x]; first[x] = rd; } } void Tarjan(int v) { low[v] = dfn[v] = ++t; stack[++top] = v; instack[v] = true; for(int i = first[v]; i ; i = road[i].next) { int y = road[i].y; if(dfn[y] == 0) { Tarjan(y); low[v] = min(low[v], low[y]); } else if(instack[v]) low[v] = min(low[v], dfn[y]); } if(dfn[v] == low[v]) { cnt++; do { num[cnt]++; belong[stack[top]] = cnt; instack[stack[top]] = false; top--; }while (stack[top + 1] != v); } } int Solve() { for(int i = 1; i <= N; ++i) if(!dfn[i]) Tarjan(i); for(int i = 1; i <= M; ++i) { int x = road[i].x, y = road[i].y; if(belong[x] == belong[y]) continue; out[belong[x]]++; } int maybe = -1; for(int i = 1; i <= cnt; ++i) { if(out[i] == 0) { if(maybe != -1) return 0; maybe = i; } } return num[maybe]; } int main() { ios::sync_with_stdio(false); Read(); cout << Solve(); return 0; }