题目链接:
题目描述:
有n只牛,牛之间存在一些关系,比如a认为b很受欢迎,b认为c很受欢迎,这样呢,a也会认为c很受欢迎,问根据给出的关系,有多少头牛被其他所有的牛都认为是受欢迎的?
解题思路:
对于一个有向无环图来说,其中有且仅有一个点出度为零,那么这个特殊的点,可以由其他任何点到达。那么接下来我们直接对所给的图进行强连通分量划分,然后把每个强连通分量看做一个点,判定出度为零的点有几个,如果有一个就输出这个点对应的强连通分量含有的节点个数,否则为零。
1 #include <cstring> 2 #include <cstdio> 3 #include <string> 4 #include <algorithm> 5 using namespace std; 6 7 const int maxn = 10005; 8 struct node 9 { 10 int to, next; 11 } edge[maxn*5]; 12 int head[maxn], id[maxn], tot, cnt, time, top; 13 int dfn[maxn], low[maxn], vis[maxn], stack[maxn], instack[maxn]; 14 15 void init() 16 { 17 tot = top = 0;//top指向栈顶 18 cnt = 0;//强连通分量 19 time = 1;//时间戳 20 memset (id, 0, sizeof(id));//i所属的连通分量 21 memset (stack, 0, sizeof(stack));//dfs到的元素进栈 22 memset (instack, 0, sizeof(instack));//i是否在栈中 23 memset (head, -1, sizeof(head)); 24 memset (dfn, 0, sizeof(dfn));//进栈时间 25 memset (low, 0, sizeof(low));//i能到达的最早进栈的节点的进栈时间 26 memset (vis, 0, sizeof(vis));//强连通分量是否有出度 27 } 28 void Add (int from, int to) 29 { 30 edge[tot].to = to; 31 edge[tot].next = head[from]; 32 head[from] = tot++; 33 } 34 void Tarjan (int u) 35 { 36 dfn[u] = low[u] = time ++; 37 instack[u] = 1; 38 stack[top++] = u; 39 for (int i=head[u]; i!=-1; i=edge[i].next) 40 { 41 int v = edge[i].to; 42 if (!dfn[v])//v没有dfs到过 43 Tarjan(v); 44 if (instack[v])//v在栈中 45 low[u] = min (low[v], low[u]); 46 } 47 if (low[u] == dfn[u]) 48 {//找到一个强连通分量 49 cnt ++; 50 while (1) 51 {//在栈中弹出强连通分量 52 int v = stack[--top]; 53 instack[v] = 0; 54 id[v] = cnt; 55 if (v == u) 56 break; 57 } 58 } 59 } 60 61 int main () 62 { 63 int n, m; 64 while (scanf ("%d %d", &n, &m) != EOF) 65 { 66 init (); 67 while (m --) 68 { 69 int from, to; 70 scanf ("%d %d", &from, &to); 71 Add (from, to); 72 } 73 for (int i=1; i<=n; i++) 74 if (!dfn[i])//i点没进过栈,i点进栈继续dfs 75 Tarjan(i); 76 int sum = 0, x; 77 for (int i=1; i<=n; i++) 78 for (int j=head[i]; j!=-1; j=edge[j].next) 79 if (id[i] != id[edge[j].to])//id[i] 到 id[edge[j].to这条边不在强连通分量中,记录id[i]分量有出度 80 vis[id[i]] ++; 81 for (int i=1; i<=cnt; i++) 82 if (!vis[i]) 83 { 84 sum ++; 85 x = i; 86 } 87 88 if (sum == 1) 89 { 90 sum = 0; 91 for (int i=1; i<=n; i++) 92 if (id[i] == x) 93 sum ++; 94 printf ("%d ", sum); 95 } 96 else 97 printf ("0 "); 98 } 99 return 0; 100 }