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
题解
好久没打$tarjan$了,码在这当模板存着。
1 //It is made by Awson on 2017.9.24 2 #include <set> 3 #include <map> 4 #include <cmath> 5 #include <ctime> 6 #include <queue> 7 #include <stack> 8 #include <vector> 9 #include <string> 10 #include <cstdio> 11 #include <cstdlib> 12 #include <cstring> 13 #include <iostream> 14 #include <algorithm> 15 #define LL long long 16 #define Min(a, b) ((a) < (b) ? (a) : (b)) 17 #define Max(a, b) ((a) > (b) ? (a) : (b)) 18 using namespace std; 19 const int N = 10000; 20 const int M = 50000; 21 int Read() { 22 char ch = getchar(); 23 int sum = 0; 24 while (ch < ‘0‘ || ch > ‘9‘) ch = getchar(); 25 while (ch >= ‘0‘ && ch <= ‘9‘) sum = (sum<<3)+(sum<<1)+ch-48, ch = getchar(); 26 return sum; 27 } 28 29 int n, m, u, v; 30 struct tt { 31 int from, to, next; 32 }edge[M+5]; 33 int path[N+5], top; 34 int dfn[N+5], low[N+5], t; 35 bool vis[N+5]; 36 int S[N+5], topS; 37 int sccno[N+5], sccnum; 38 int in[N+5], tot[N+5]; 39 40 void add(int u, int v) { 41 edge[++top].to = v; 42 edge[top].from = u; 43 edge[top].next = path[u]; 44 path[u] = top; 45 } 46 void tarjan(int r) { 47 dfn[r] = low[r] = ++t; 48 vis[r] = 1; 49 S[topS++] = r; 50 for (int i = path[r]; i; i = edge[i].next) { 51 if (!dfn[edge[i].to]) { 52 tarjan(edge[i].to); 53 low[r] = Min(low[edge[i].to], low[r]); 54 } 55 else if (vis[edge[i].to]) 56 low[r] = Min(low[r], dfn[edge[i].to]); 57 } 58 if (dfn[r] == low[r]) { 59 sccnum++; 60 while (topS > 0 && S[topS] != r) { 61 vis[S[--topS]] = 0; 62 sccno[S[topS]] = sccnum; 63 tot[sccnum]++; 64 } 65 } 66 } 67 void work() { 68 n = Read(), m = Read(); 69 for (int i = 1; i <= m; i++) { 70 u = Read(), v = Read(); 71 add(u, v); 72 } 73 for(int i = 1; i <= n; i++) 74 if(!dfn[i]) tarjan(i); 75 for (int i = 1; i <= m; i++) 76 if (sccno[edge[i].to] != sccno[edge[i].from]) 77 in[sccno[edge[i].from]]++; 78 int ans = 0, cntt = 0; 79 for (int i = 1; i <= sccnum; i++) 80 if (!in[i]) cntt++, ans=i; 81 if (cntt == 1) printf("%d\n", tot[ans]); 82 else printf("0\n"); 83 } 84 int main() { 85 work(); 86 return 0; 87 }
时间: 2024-10-10 22:30:21